如何在 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 typeThe 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 计算相对分支位移。