要将普通的(接近直接相对的)call
制成绝对地址,请使用NASM或AT&T语法编写call 0x1234567
,并且汇编程序+链接程序负责计算rel32
以从链接程序将call
指令放置到的任何位置到达该目标。
例如在Linux上,使用yasm -felf64 foo.asm && ld foo.o -o foo
将其组装成一个静态的64位ELF可执行文件,然后使用objdump -drwC -Mintel foo
对其进行反汇编,将为您提供:
foo: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: e8 e2 44 e3 00 call 1234567 <_end+0xc344df>
链接器根据对象文件中的
0x1234567
重定位,计算出正确的rel32从0x400080+5
到达R_X86_64_PC32
: 0: e8 00 00 00 00 call 5 <_start+0x5> 1: R_X86_64_PC32 *ABS*+0x1234563
如何使MASM和/或MSVC内联asm做到这一点?
MSVC不接受
_asm { call 1234567h; }
。错误是C2415: improper operand type
。 The only SO answer I've found建议对内存或寄存器中的地址使用间接jmp的变通方法,但是由于难以使用的工具而导致低效率的机器代码并不是一个很好的解决方案。我根本没有MASM,所以我只能尝试MSVC内联式asm(不是同一回事)on the Godbolt compiler explorer。
您可以设置标签的地址并将其用作
call symbol
的目标吗?就像GAS的.set symbol, 0x1234567
一样,它使您可以给符号提供地址,而无需在任何地方实际编写symbol:
。您可以直接使用
db 0E8h
/dd 1234567h - ($ + 4)
发出编码吗?可能不是in NASM that only works with label - $
,不是absolute - label
我对答案最感兴趣,因此可以将其包含在有关jmp/调用绝对地址的规范答案中:Call an absolute pointer in x86 machine code绝对不是我要实际使用的任何代码。
最佳答案
MASM不支持此功能,因为COFF目标文件格式不支持必要的重定位。 (或者不正确地支持它?根据NASM错误消息。)
在call 0x76cd75c0
中使用nasm -f win32
语法会产生错误:
error: Win32 COFF does not correctly support relative references to absolute addresses
我不知道以实模式平面二进制文件为目标的MASM是否可以做到(没有目标文件必须描述链接器的重定位),但是不幸的是,MASM可能根本没有语法设计。
另请参见Error when calling function in user32.dll directly。我在Linux桌面上尝试了
nasm -fwin32
2.13.02,但遇到了同样的错误。一种未经测试的可能的解决方法可能是使用该绝对地址的符号定义创建
.obj
,例如org 0deadbeefH
global my_target
my_target:
在NASM中,或者在MASM中执行。
然后,在MASM或MSVC inline-asm中,您可以使用
jmp my_target
并与该.obj
链接。从理论上讲,这可能可以解决在目标文件中表示重定位的问题,并获得链接器以计算相对分支位移。关于assembly - 如何在MASM中为近乎直接的相对调用/jmp编写绝对目标,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50058523/