读书笔记_CALL和RET指令

 

   CALL指令是x86CPU中专门用作函数调用的指令,它的作用就是将当前的程序指针(EIP寄存器)值保存到栈中(称为linking information),然后转移到(branch to)目标操作数所指定的函数(被调用过程)继续执行。

   根据被调用过程是否位于同一个代码段,CALL调用被分为近调用(Near Call)和远调用(Far Call)两种。在近调用中CPU的操作如下:

A.      将EIP寄存器的当前值压入到栈中供返回时使用

B.      将被调用过程的偏移(相对于当前段)加载到EIP寄存器中

C.      开始执行被调用过程

对于远调用,CPU执行的操作如下:

A. 将CS寄存器的当前值压入到栈中供返回时使用

B. 将EIP寄存器的当前值压入到栈中返回时使用

C. 将包含被调用过程的代码段的段选择子加载到CS寄存器

D. 被调用过程的偏移加载到EIP寄存器

E.  开始执行被调用过程

可以看出近调用和远调用的差异在于是否处理段寄存器,因为近调用发生在一个代码内的调用,因此不需要向栈中压入和切换代码段,而远调用因为发生在不同的代码段间,因此需要保存和切换代码段。但对于NT系列的windows,因为使用了平坦内存,在同一进程内的代码都是在一个大的4GB段中,因此不必再考虑段的差异,几乎所有时候使用的都是近调用。

下面来看RET指令,RET指令用于从被调用过程返回到发起调用的过程,RET指令可以有一个可选的参数n,用于指定ESP寄存器要递增的字节数,ESP递增n个字节相当于从栈中弹出n个字节,经常用来释放压在栈上的参数。相对于近调用的返回称为近返回(Near Return),相对于远调用的被称为远返回(Far Return)。

对于近返回,CPU所执行的操作如下:

1.  将位于栈顶的数据弹出到EIP寄存器,这个值应该是发起近调用时CALL指令压入的返回地址。

2.  如果RET指令包含参数n,那么便将ESP寄存器的字节数递增n。

3.  继续执行程序指针所指向的指令,通常就是父函数中调用指令的下一条指令。

而对于远返回,在第一步和第二步之间,CPU会弹出执行远调用时压入的CS寄存器。所以,RET指令只是单纯地返回到执行这条指令时栈顶所保存的地址,如果栈寄存器(ESP)没有指向合适的位置或栈上的地址被破坏了,那么RET指令就返回到其他地方。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值