Fork me on GitHub

CSAPP-9

过程

栈帧的结构

栈帧是程序栈的一段,程序栈是储存器的一段。

起始地址:储存在%ebp寄存器(桢指针)

结束地址:储存在%esp寄存器(栈顶指针)

栈指针会在运行时移动,所以大部分时候,在访问存储器的时候会基于帧指针访问,因为在一直移动的栈指针无法根据偏移量准确的定位一个存储器位置。

过程的实现

  1. 备份原来指针

    1
    2
    pushl %ebp
    movl %esp, %ebp
  2. 给临时变量分配预留内存

    1
    subl $16,%esp
  3. 值压入栈顶(备份)

    1
    pushl %ebx
  4. 使用建立好的栈帧,mov,push,pop

  5. 从栈帧中将备份的值恢复到寄存器

  6. 释放被调用的栈帧,栈指针增大

    1
    movl %ebp,%esp
  7. 调整栈帧两端,第六步调整了栈指针, 只需要将备份的原桢指针弹到%ebp

    1
    popl %ebp
  8. 弹出返回地址,跳出当前过程,继续执行调用者的代码。(ret)

过程相关指令:call、leave、ret

call:将返回地址压入栈顶,将程序跳转到当前调用的方法的起始地址。

leave:栈指针指向桢指针,弹出备份的原桢指针到%ebp

ret:栈顶的返回值弹出到PC,按照PC指示的指令地址继续执行程序。

寄存器的使用规则

%eax、%edx、%ecx:调用者保存寄存器。这三个寄存器由调用者P来保存,而对于Q来说,Q可以随便使用,用完了就不用再管了。

%ebx、%esi、%edi:被调用者保存寄存器。这三个寄存器由被调用者Q来保存,Q可以使用这三个寄存器,但是如果里面有P的变量值,Q必须保证使用完以后将这三个寄存器恢复到原来的值,这里的备份,其实就是上面那8个步骤中第3个步骤做的事情。

0%