【问题标题】:What happens if ret is used without a call?如果在没有调用的情况下使用 ret 会发生什么?
【发布时间】:2020-06-14 20:05:41
【问题描述】:

我对汇编很陌生,我想知道 ret 的行为。如果我在代码期间从不使用调用,而是在末尾添加一个 ret,则代码只是回到开头。这是不使用呼叫时的默认行为吗?如果我使用了 jmp,如果仍然没有使用调用,那会影响 ret 的行为吗?

【问题讨论】:

    标签: assembly avr


    【解决方案1】:

    call将下一条指令的地址放入调用栈,然后跳转到目标地址。

    ret 从调用栈中弹出最后一个地址,然后跳转到这里。好像如果栈是空的,就返回0x00000000,然后跳转到程序的开头。 至少在某些系统中。由于地址空间违规,您不应该使用它。

    jmp 对调用堆栈没有影响,所以它不会修改ret 的行为。

    编辑:正如@PeterCordes 所写;如果您使用pushpop,它们可以写入堆栈内存,而ret 会弹出它。

    【讨论】:

    • 如果您在ret 之前使用了其他指令,例如push,它会弹出您推送的任何内容。 call 不是唯一可以写入堆栈内存的指令。 ret 基本上只是弹出指令指针。
    • 快速抛开,如果您有兴趣超越当前处理器:虽然 AVR 和 x86 以及许多其他处理器返回从堆栈获取的返回地址,但也有返回返回地址的处理器取自一个特殊的寄存器。
    【解决方案2】:

    在许多系统中,启动/启动代码实际上调用 main() 函数(或其等效函数),例如使用https://www.nongnu.org/avr-libc/ 的裸机AVR 程序(这样做的好处是编译器可以像其他函数一样将main() 编译为函数,不需要任何特殊处理)。

    因此,当您在 main() 中的用户代码执行 ret 时(即使您的用户代码本身从未真正调用 anthing),您的用户代码将从该隐式调用返回,并且启动/启动代码将继续运行。

    现在的问题是main() 返回后启动/启动代码的作用。它可能会进入无休止的繁忙循环、停止系统、关闭电源、重新启动等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 2020-04-25
      • 2019-07-27
      • 1970-01-01
      • 2011-06-02
      • 1970-01-01
      相关资源
      最近更新 更多