【问题标题】:How can I jump to a specific line without using labels?如何在不使用标签的情况下跳转到特定行?
【发布时间】:2019-12-30 10:39:54
【问题描述】:

假设我有一个返回的调用函数,我可以让它返回到返回地址之前的 x 行吗?例如。

call foo --> line 72 - calling bar will return here.
mov ax,1
call bar --> line 74

bar:
mov ax,2
ret (-2)

我的目标是创建一个可调用函数,该函数将始终返回到调用地址之前的 2 行,而无需使用十亿个标志和标签。

【问题讨论】:

    标签: assembly x86-16


    【解决方案1】:

    不能,x86 指令是可变长度的。没有办法知道通过在call 之前向后退 2 条指令来减少您的退货地址多少。

    即使您愿意编写反汇编程序/解码器,也没有办法明确向后解​​码 x86 指令。例如如果您返回一个字节并看到 0x90,您不知道这是 NOP 还是 add dx, 0x9000 的最后一个字节。

    从已知的函数开始标签向前解码是像 GDB 这样的调试器所做的。但是,我认为扫描符号表和反汇编对于你正在做的任何事情来说都太繁重了。


    我唯一想到的就是在你的调用序列中非常严格,所以这总是一个固定的字节数;例如在这里,您在 call bar 之前使用了两条 3 字节指令(call rel16mov ax, imm16)。而call bar本身也是3个字节。

    或者总是在返回地址之前返回固定数量的字节,并让调用者选择在该窗口中放置哪些/多少指令。


    顺便说一句,你这样做的方法是修改堆栈上的返回地址:

    pop ax            ; could use any register that your function destroys
    sub ax, 9
    push ax
    ret
    

    如果您已将 BP 设置为帧指针,例如 sub word [bp+2], 9,则相对于 BP 进行寻址。


    请参阅What methods can be used to efficiently extend instruction length on modern x86? 了解在不添加更多指令的情况下延长指令的技术,以防您想在调用前使用更短的指令,例如mov cx, bx。例如您可以改用lea cx, [byte 0 + bx](NASM 语法:byte 0 强制 disp8 为0,因此编码为8D 4F 00)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 2018-06-28
      • 2018-07-20
      • 1970-01-01
      相关资源
      最近更新 更多