如何在 MASM 中为近直系亲属 call/jmp 编写绝对目标
How to write an absolute target for a near direct relative call/jmp in MASM
要对绝对地址进行正常(近直接相对)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>
链接器根据目标文件中的 R_X86_64_PC32
重定位计算出从 0x400080+5
到达 0x1234567
的正确 rel32:
0: e8 00 00 00 00 call 5 <_start+0x5> 1: R_X86_64_PC32 *ABS*+0x1234563
如何让 MASM and/or MSVC inline-asm 做到这一点?
MSVC 不接受 _asm { call 1234567h; }
。错误是 C2415: improper operand type
。 The only SO answer I've found 建议使用内存或寄存器中地址的间接 jmp 的变通方法,但由于工具难以使用而生成低效的机器代码并不是一个很好的解决方案。
我根本没有 MASM,所以我只能尝试 MSVC inline-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 的规范答案中到一个绝对地址:Call an absolute pointer in x86 machine code 绝对不是我想实际使用的任何代码。
MASM 不支持这个,因为 COFF 对象文件格式不支持必要的重定位。 (或者 不正确 支持它?根据 NASM 错误消息。)
在nasm -f win32
中使用call 0x76cd75c0
语法会报错:
error: Win32 COFF does not correctly support relative references to absolute addresses
我不知道针对实模式平面二进制文件的 MASM 是否可以做到这一点(其中没有必须描述到 linker 的重定位的目标文件),但可能 MASM 的设计没有不幸的是,它根本没有语法。
另见 。我确实在我的 Linux 桌面上尝试了 nasm -fwin32
2.13.02,但遇到了同样的错误。
一个未经测试的可能解决方法可能是创建一个.obj
,其中包含该绝对地址的符号定义,例如
org 0deadbeefH
global my_target
my_target:
在 NASM 中,或者您在 MASM 中这样做。
然后在 MASM 或 MSVC inline-asm 中,您可以将 jmp my_target
和 link 与 .obj
一起使用。从理论上讲,这可能会解决在目标文件中表示重定位的问题,并让 linker 计算相对分支位移。
要对绝对地址进行正常(近直接相对)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>
链接器根据目标文件中的 R_X86_64_PC32
重定位计算出从 0x400080+5
到达 0x1234567
的正确 rel32:
0: e8 00 00 00 00 call 5 <_start+0x5> 1: R_X86_64_PC32 *ABS*+0x1234563
如何让 MASM and/or MSVC inline-asm 做到这一点?
MSVC 不接受 _asm { call 1234567h; }
。错误是 C2415: improper operand type
。 The only SO answer I've found 建议使用内存或寄存器中地址的间接 jmp 的变通方法,但由于工具难以使用而生成低效的机器代码并不是一个很好的解决方案。
我根本没有 MASM,所以我只能尝试 MSVC inline-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 的规范答案中到一个绝对地址:Call an absolute pointer in x86 machine code 绝对不是我想实际使用的任何代码。
MASM 不支持这个,因为 COFF 对象文件格式不支持必要的重定位。 (或者 不正确 支持它?根据 NASM 错误消息。)
在nasm -f win32
中使用call 0x76cd75c0
语法会报错:
error: Win32 COFF does not correctly support relative references to absolute addresses
我不知道针对实模式平面二进制文件的 MASM 是否可以做到这一点(其中没有必须描述到 linker 的重定位的目标文件),但可能 MASM 的设计没有不幸的是,它根本没有语法。
另见 nasm -fwin32
2.13.02,但遇到了同样的错误。
一个未经测试的可能解决方法可能是创建一个.obj
,其中包含该绝对地址的符号定义,例如
org 0deadbeefH
global my_target
my_target:
在 NASM 中,或者您在 MASM 中这样做。
然后在 MASM 或 MSVC inline-asm 中,您可以将 jmp my_target
和 link 与 .obj
一起使用。从理论上讲,这可能会解决在目标文件中表示重定位的问题,并让 linker 计算相对分支位移。