示例1.
以下堆栈帧视图的屏幕快照显示了12个字节(包括在红色框中)缓冲区:
示例2。
以下不同堆栈帧视图的屏幕快照再次显示了12个字节的缓冲区:之所以命名为
db ?; undefined
,是因为它无法弄清楚它是如何使用的。我还意识到IDA通过监视ESP自动计算堆栈帧的大小。我认为这可能与非挥发性寄存器保存区有关。但是,在示例1中清楚地显示Saved regs: 0
,在示例2中清楚地显示Saved regs: 4
。我很困惑,下面是我的问题:为什么IDA Pro在堆栈帧视图中在局部变量上方(较低地址)显示某些缓冲区或填充?这两个视图都恰好显示了12个字节的缓冲区是一个巧合吗?它是某些调用约定或编译器所特有的吗?
#1 楼
IDA在对整个函数的静态分析过程中始终跟踪堆栈指针(ESP)的值。 ESP的最大负值(相对于函数开头)用于确定堆栈框架的大小。关于您发布的堆栈框架为何在顶部具有“未定义”字节的原因,这是因为IDA无法自动确定是否或如何使用这些堆栈偏移量。
评论
非常感谢你的回复。我确实意识到您提到的一切。但是,它不能解决我的问题。我已经澄清了我的问题。希望它更清晰一些,您可以帮助我。
– PSS
13年6月19日在3:20
#2 楼
非常感谢您的回答和评论。在阅读您的评论并准备更新我的问题时,我找到了答案。我必须感谢Igor Skochinsky,他要求我提供功能的序言说明。这两个函数都使用cdecl调用约定。但是,调用约定与此缓冲区无关。它的序言如下:这些寄存器归类为“被调用方保存的寄存器”,此“缓冲区”称为“非易失性寄存器保存区”。
根据x86约定(也适用于x64),寄存器分为呼叫者保存的寄存器和呼叫者保存的寄存器。
调用者保存的寄存器也称为易失性寄存器。这些是核心CPU寄存器,例如EAX,EDX和ECX。调用函数(Caller)负责在进行调用之前将易失性寄存器保存到通常的运行时堆栈中。
被调用者保存的寄存器称为非易失性寄存器。这些是核心CPU寄存器,例如EBX,ESI,EDI,ESP和EBP。按照惯例,这些寄存器中的值将由被调用方函数保留。如果将在被调用方中使用任何非易失性寄存器,则被调用方负责将寄存器保存到运行时堆栈中。此外,被调用方还负责在返回调用方功能之前恢复这些寄存器。
易失性和非易失性寄存器的使用方式是由编译器驱动的。以下白皮书《 x86汇编指南》更详细地描述了Caller和Callee规则。
#3 楼
屏幕快照显示您正在检查IDA的详细堆栈视图。惯例 ?给我们这个子例程的序言和结尾,以便我们可以了解如何分配和清理堆栈。因此,如果这是用高级语言编写的普通应用程序的堆栈框架(不是恶意软件,也不是而不是专门针对约定调用,那么我认为我们可以同意,由于某种原因,编译器分配的堆栈空间超出了此函数所需的空间。知道为什么编译器会这样做,但这就是您的选择。
评论
谢谢您的意见。我知道这是什么约定。我没有问这个。我想知道的是,此特定缓冲区是否与某些调用约定有关?我正在更新我的问题以澄清这一点。
– PSS
2013年6月19日13:31
@PSS我看不到我的答案来解释什么是调用约定,但是如果您足够友好地向我们提供此子例程的序言和结尾,以便确定这是否与调用约定有关,那么我们可以帮你。
– nomilk
2013年6月19日15:37
我已经提供了答案。谢谢您的意见。
– PSS
2013年6月19日15:40
评论
出于性能(内存对齐)或防止溢出的原因,编译器可能会添加堆栈填充,但是这些并没有很好地显示出来。您可以显示该函数的反汇编代码吗?添加功能序言说明。