【发布时间】:2014-05-06 10:07:13
【问题描述】:
出于好奇,我决定手工组装一些 x86 代码。到目前为止,我一切正常,但我无法确定 call 指令的正确编码。
我知道它基本上应该是E8 xx xx xx xx,其中xx xx xx xx是我要跳转到的地址。
我尝试编码的方式是这样的(NASM):
extern _printf
; ...
db 0xe8
dd _printf
组装和链接都很好,但是程序崩溃了。
我查看了 NASM 如何组装指令 call _printf,它生成的 xx xx xx xx 与我的不同。我想知道是我指定的地址不正确还是什么,但是代码
times 512 nop
dd _printf
times 512 nop
产生大量的90s 围绕着我从我手工组装的call 获得的相同地址,这意味着_printf 的实际地址不是我应该传递的。
我在这里错过了什么?
(另外:我很好奇call 的另一种编码,以FF 开头的那个。有什么区别?)
【问题讨论】:
-
E8使用相对寻址:"E8 cdCALL rel32调用近、相对、相对于下一条指令的位移。32 位位移符号在 64 位中扩展到 64 位模式。” 请参阅英特尔的软件开发人员手册第 2 卷。