JZ没有在堆栈中放置返回地址吗



我正在阅读汇编代码优化手册第2.3节常见编码陷阱-第9页

  1. 不匹配的PUSH和POP指令。对于通过函数的所有可能路径,PUSH和POP指令的数量必须相等。示例:

    push ebx
    test ecx, ecx
    jz   Finished
    ...
    pop  ebx
    Finished:       ; Wrong! Label should be before pop ebx
    ret
    

这里,如果ECX为零,则不会再次弹出推送的EBX值。结果是RET指令将弹出EBX的前一个值,并跳转到错误的地址。

我的疑问是:jz指令不是将返回地址存储在堆栈中吗?其他指令如jmpjgjgejljle等呢?

不,不是Call指令将返回地址推送到堆栈,jump(包括条件跳转(指令则不会。这就是呼叫和跳跃之间的根本区别。

如果你想知道指令的作用,你应该总是参考官方文件中的描述,例如。https://www.felixcloutier.com/x86/它是英特尔手册的HTML副本。jcc(包括je(的描述中没有提到推送返回地址,这告诉你它不推送。另一方面,call的描述中明确说明了返回地址是推送的,并详细说明了如何推送:

执行近调用时,处理器将EIP寄存器的值(包含call指令后面的指令的偏移量(推送到堆栈上(稍后用作返回指令指针(。然后,处理器分支到目标操作数指定的当前代码段中的地址。

Jump指令通常用于在函数内传输控制,用于循环(while(、条件执行(if(等结构。在大多数此类情况下,您永远不想返回到跳转的位置,因此推送返回地址是没有用的,只需要浪费额外的指令就可以将其从堆栈中删除。

最新更新