3

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

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

bar:
mov ax,2
ret (-2)

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

4

1 回答 1

6

你不能,x86 指令是可变长度的。没有办法知道通过在call.

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

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


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

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


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

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

或者,BP如果您已将 BP 设置为帧指针,例如sub word [bp+2], 9.


请参阅可以使用哪些方法来有效地扩展现代 x86 上的指令长度?用于在不添加更多指令的情况下使指令更长的技术,以防您想mov cx, bx在调用之前使用更短的指令。例如,您可以改用lea cx, [byte 0 + bx](NASM 语法:byte 0强制 disp8 为0,因此编码为8D 4F 00)。

于 2019-12-30T10:58:55.740 回答