【问题标题】:Assembly CALL and RET stack汇编 CALL 和 RET 堆栈
【发布时间】:2021-05-31 13:47:59
【问题描述】:

我有疑问。当我知道时

call <address>

等价于

push rip  
jmp <address>

我也知道

ret

等价于

pop rip
jmp <rip>

但是如果我们跳转到 rip 为什么我们不重新开始这个循环,因为我们在跳转之前推送 rip 并且在跳转时指定 rip?你能解释一下我们如何在代码中传递这个跳转

【问题讨论】:

  • 因为 RIP 总是指向下一条要执行的指令——而不是当前指令。
  • 来自英特尔的手册:"3.5 INSTRUCTION POINTER指令指针(EIP)寄存器包含当前代码段中下一个要执行的指令的偏移量“.
  • 没错,但是当我们在下一条指令(跳转)上推送它时,当我们弹出它时,它仍然在跳转时指定
  • 感谢 Doug Currie 先生,我明白了

标签: assembly nasm


【解决方案1】:

各种处理器有不同的处理方式。在某些情况下,call 在调用后推送指令的地址。在其他情况下,ret 在跳转前将调用指令的长度添加到返回地址。

第一种方法更灵活,因为它可以在call 中使用具有不同指令长度的各种寻址模式。指令解码器也可能在处理call 时已经知道下一条指令的位置。

【讨论】:

  • 对于 x86,call 在调用后推送指令的地址。这是调用执行时的当前 RIP 值;相对于指令的结尾,RIP 相对寻址模式的工作方式相同。 x86 指令不是固定长度的,因此ret 无法知道它是否被 5 字节 call &lt;rel32&gt; 调用(或前面的一些前缀,例如来自链接器“放松”另一种编码),或 2 字节 call rax 间接,6 字节 call [rel func_ptr],或 7 或 8 字节 call [rdi + r10*8 + jump_table_base]
猜你喜欢
  • 2010-11-04
  • 1970-01-01
  • 2015-09-04
  • 2016-11-23
  • 2014-10-04
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
相关资源
最近更新 更多