如何在 MASM 中为近直接相对调用/jmp 编写绝对目标

Pet*_*des 5 x86 assembly masm call visual-c++

为了使call绝对地址正常(接近直接相对),在您编写的 NASM 或 AT&T 语法中call 0x1234567,汇编器 + 链接器负责计算 arel32以从链接器放置call指令的任何位置到达该目标。

例如,在 Linux 上用 将其组装成静态 64 位 ELF 可执行文件yasm -felf64 foo.asm && ld foo.o -o foo,然后用 反汇编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>
Run Code Online (Sandbox Code Playgroud)

链接器根据目标文件中的重定位计算了0x1234567从到达的正确 rel32 :0x400080+5R_X86_64_PC32

  0:   e8 00 00 00 00          call   5 <_start+0x5>   1: R_X86_64_PC32        *ABS*+0x1234563
Run Code Online (Sandbox Code Playgroud)

你如何让 MASM 和/或 MSVC inline-asm 做到这一点?

MSVC 不接受 _asm { call 1234567h; }. 错误是 C2415: improper operand type我发现的唯一 SO 答案建议使用具有内存或寄存器中地址的间接 jmp 的解决方法,但由于难以使用的工具而使机器代码效率低下并不是一个很好的解决方案。

我根本没有 MASM,所以我只能在 Godbolt compiler explorer 上尝试 MSVC inline-asm(这不是一回事)。

您可以设置标签的地址并将其用作目标call symbol吗?就像 GAS 一样,.set symbol, 0x1234567它可以让你给一个符号一个地址,不必实际写symbol:任何地方。

你能直接用db 0E8h/发出编码dd 1234567h - ($ + 4)吗?可能不是,在 NASM 中只适用于label - $,而不是absolute - label


我对答案最感兴趣,所以我可以将它包含在我关于 jmp/call to an absolute address 的规范答案中:在 x86 机器代码中调用绝对指针 绝对不是我想要实际使用的任何代码。

Pet*_*des 1

MASM 不支持这一点,因为 COFF 目标文件格式不支持必要的重定位。(或者没有正确支持它?根据 NASM 错误消息。)

使用call 0x76cd75c0中的语法nasm -f win32会出现错误:

error: Win32 COFF does not correctly support relative references to absolute addresses
Run Code Online (Sandbox Code Playgroud)

我不知道针对实模式平面二进制文件的 MASM 是否可以做到这一点(其中没有必须描述链接器重定位的目标文件),但不幸的是,MASM 可能只是在设计时根本没有语法。


另请参阅直接调用 user32.dll 中的函数时出错nasm -fwin32我自己在 Linux 桌面上尝试了2.13.02 并得到了同样的错误。


未经测试的可能解决方法.obj可能是为该绝对地址创建一个带有符号定义的变量,例如

org 0deadbeefH
global my_target
my_target:
Run Code Online (Sandbox Code Playgroud)

在 NASM 中或者在 MASM 中执行此操作。

然后在 MASM 或 MSVC inline-asm 中,您可以使用jmp my_target并链接该.obj. 理论上,这可能会解决在目标文件中表示重定位的问题,并让链接器计算相对分支位移。