假设我们有一个16字节的数组,以及一些4字节的整数。在调用函数之前,我们将数组推入堆栈;然后我们推整数。
现在,我的理解是“下面”的基指针是返回地址和参数;正上方,以及我们在顶部的堆栈指针“下方”是我们已经推入堆栈(和寄存器)的局部变量。
如何确定数组起始地址的位置以及整数?简单地为数组做“ebp - 16”,为整数做-20是否准确,还是有一个我缺少的细节?我们是否也可以参考这些相对于esp的东西,或者这是非常规的?
此外,是否有可能以不同方式处理此寻址的实现?
最后,是否有必要在我们的函数结束之前从堆栈中弹出这些东西?
答案 0 :(得分:1)
您按下数组的地址,而不是数组的全部内容。
此地址的大小在32位系统上为4个字节,在64位系统上为8个字节。
既然你知道你正在使用什么系统,那么计算每个参数的地址很容易。
最后一件事#34;留在堆栈上#34;函数返回之前是......返回的值。
所以是的,除此之外的所有内容都会在函数返回之前弹出堆栈。
作为旁注,一些编译器通过寄存器而不是堆栈传递一些参数。
答案 1 :(得分:1)
"推"意思是:减去从ESP推送的元素的大小,然后将元素写入ESP的内存。在调用函数时,"返回地址"被推了。
这意味着:当输入函数时,返回地址将位于ESP + 0,ESP + 4处的整数和ESP + 8处数组的第一个字节。
由被调用的函数来初始化EBP寄存器。通常,EBP将初始化为ESP的原始值减去4,因此整数位于EBP + 8,数组位于EBP + 12(十进制)。通常使用以下代码:
push EBP ; Save on stack so the old value can be restored later
mov EBP,ESP ; Initialize the EBP register
然而 - 再一次 - 如果调用函数没有初始化EBP寄存器,它没有任何有用的值。
编程函数的程序员(或编译C代码的编译器)必须知道堆栈中的哪些数据以及这些数据的位置。因此,没有可能找到"数据的位置,但您必须以数据位于给定地址的方式设计程序。
顺便说一句:用户" barak manos"是的,当他说通常你推送一个数组的地址,而不是一个数组本身。但是,几乎没有例外,数组的内容被压入堆栈(例如函数" WinUsb_ControlTransfer")。