功能序言在内存方面

时间:2016-05-30 21:19:15

标签: memory assembly stack

我试图了解函数prolog如何在汇编中工作。我的书显示以下代码:

    push    %ebp
    movl    %ebp, %esp

在push的定义中,它表示它将ESP的值减少4(字节?),然后将操作数放入ESP指定的内存中。但是这不会覆盖一些数据,如图所示? enter image description here

此外我假设每个段都是4(字节?)但是我很确定函数可以有超过4个字节的已分配堆栈空间?

接下来,第二条指令将ESP中的内容移动到EBP中,但是有什么需要呢?那已经存在了吗?当调用pop时,它如何知道从堆栈中带走多少? (我解释的所有内容都假设指令movpush从指向它们的位置开始,并在执行任何操作时上升到存储器中。

2 个答案:

答案 0 :(得分:3)

x86机器上的堆栈从较高地址到较低地址逐渐减少 这由push指令的语义反映出来:

push ebp

在语义上等同于

sub esp, 04h
mov DWORD [esp], ebp  

从技术上讲,我们说堆栈是完全下降完整因为esp总是指向推送的最后一个值而降序原因很明显。

事实上,堆栈指针上方的所有内容都被某些代码推送,因此它被初始化并隐式分配内存。
相反,堆栈下面的所有内容是可用内存。

因此push ebp不会覆盖任何有用的内容,通常 push 不会这样做。

mov ebp, esp不接受 EBP 的内容(本来是mov ebp, DWORD [esp],而是复制 ESP的内容将自己注册到 EBP 使用 EBP 有两个原因:

  1. 它隐式使用 SS 选择器,而其他寄存器使用 DS
  2. 在16位纯代码中,只有少数寄存器可用作基础,(E)BP 是专门为此设计的。(E)BP 。 让(E)BP 指向 ESP 的值对于随机访问堆栈和固定偏移非常方便。
  3. 最后,pop指令与push指令类似,其操作数决定了操作的大小:push ax/eax/rax分别在堆栈上推送2,4和8个字节。
    程序员仍然有责任保持堆栈平衡,如果需要甚至对齐,但这通常没什么可问的。

    注意:x86内存是字节可寻址的,所以当进行间接寄存器寻址时,即当我们访问像mov eax, DWORD [ebx]这样的寄存器中指定的地址时,该数字表示地址就字节而言。
    通过 N 递减该数字意味着将 N 字节读取更低,因此从 ESP 中减去4会在中的新旧地址之间留下4个字节ESP

答案 1 :(得分:0)

布拉

寄存器推送消耗了多少字节取决于寄存器大小,而寄存器大小又取决于芯片架构。在您的示例中,您使用32位寄存器,因此每次寄存器推送将消耗4个字节。

对于x86说明,此description可能非常有用。