底层理解函数调用实现过程 栈结构 栈过程

首先寄存器使用惯例:

eip :指令地址寄存器,保存程序计数器的值,当前执行的指令的下一条指令的地址值,16位中为ip,32位为eip。eip不可以直接赋值,一般都是cpu自动加1来更新,指令call和ret以及jmp可以改变eip的值。

另外汇编代码格式有ATT和intel格式,gcc和objdump的默认格式就是ATT。几个小区别,1首先是指令ATT汇编指令后面有一个l,比如intel格式为mov,ATT格式为movl

2寄存器,ATT格式有%,比如intel格式为ebp,ATT格式为%ebp

3还有一个最主要的区别就是操作指令的,操作数的顺序是相反的,源操作数和目的操作数的顺序相反。

关于栈中的寄存器:

esp :栈指针,又叫栈顶寄存器,总是指向栈顶元素,已经压入栈的最顶上的那个元素,而不是待压入的。栈指针可以移动,通过上下移动实现栈的开辟和释放。栈是向小地址方向生长的。esp寄存器中保存的是当前栈的栈顶元素的地址。

ebp :帧指针,又叫栈基址寄存器,总是指向当前栈的栈底元素。保存的是当前栈的栈底元素的地址。帧指针不可以移动,用来作为当前栈的基址,通过对基址ebp的偏移来寻址访问栈中的其他元素的值。比如:0x8(%ebp)ebp所指向的地址值在加上0x8的地址。

ebp永远都是针对当前栈的,所以当一个函数调用了另外一个函数的时候,就需要先将调用函数的栈的ebp给入栈保存,这样避免了与被调用函数的栈ebp冲突,然后在被调用函数的栈结束调用释放的时候,恢复现场的时候,在将调用函数的ebp弹出来,这样又可以回到调用函数的栈了。

栈通过栈指针栈顶esp和帧指针栈底ebp来固定栈框。

eax :保存函数的返回值的惯用寄存器

%   :直接寻址寄存器

( )  :内存间接寻址

$ :立即数 

例如:movl $8, %eax   #把立即数8存到寄存器eax中

     movl $8, (%esp)  #把立即数8存到内存esp所指的内存地址中。

这里主要来通过函数调用来彻底弄清楚栈的过程,这里直接利用bufbomb中的一段简单的c代码,通过反汇编来分析一下其汇编代码。这个c代码很简单,就是test函数中调用了getbuf函数。

其反汇编代码为:


这里的汇编代码比较长我们来截取一下只看关于栈和函数调用的部分:

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值