How to write an absolute target for a near direct relative call/jmp in MASM
To make a normal (near direct relative) call
to an absolute address, in NASM or AT&T syntax you write call 0x1234567
, and the assembler + linker take care of calculating a rel32
to reach that target from wherever the linker puts the call
instruction.
e.g. on Linux assembling that into a static 64-bit ELF executable with yasm -felf64 foo.asm && ld foo.o -o foo
, then disassembled with objdump -drwC -Mintel foo
gives you:
foo: file format elf64-x86-64
Disassembly of section .text:
0000000000400080 <_start>:
400080: e8 e2 44 e3 00 call 1234567 <_end+0xc344df>
The linker calculated the right rel32 to reach 0x1234567
from 0x400080+5
, based on a R_X86_64_PC32
relocation in the object file:
0: e8 00 00 00 00 call 5 <_start+0x5> 1: R_X86_64_PC32 *ABS*+0x1234563
How do you get MASM and/or MSVC inline-asm to do that?
MSVC doesn't accept _asm { call 1234567h; }
. The error is C2415: improper operand type
. The only SO answer I've found suggests using a workaround of an indirect jmp with the address in memory or a register, but making inefficient machine code because of hard-to-use tools isn't a very good solution.
I don't have MASM at all, so I've only been able to try MSVC inline-asm (which is not the same thing) on the Godbolt compiler explorer.
Can you set the address of a label and use it as a target for call symbol
? Like with GAS's .set symbol, 0x1234567
which lets you give a symbol an address without having to actually writing symbol:
anywhere.
Can you emit the encoding directly with db 0E8h
/ dd 1234567h - ($ + 4)
? Probably not, in NASM that only works with label - $
, not absolute - label
I'm mostly interested in the answer so I can include it in my canonical answer about jmp/call to an absolute address: Call an absolute pointer in x86 machine code Definitely not for any code I want to actually use.
Solution 1:
MASM doesn't support this because the COFF object file format doesn't support the necessary relocation. (Or doesn't correctly support it? According to a NASM error message.)
Using the call 0x76cd75c0
syntax in nasm -f win32
gives an error:
error: Win32 COFF does not correctly support relative references to absolute addresses
I don't know if MASM targeting real mode flat binaries could do it (where there are no object files that have to describe the relocations to the linker), but probably MASM was just designed without syntax for it at all, unfortunately.
See also Error when calling function in user32.dll directly. I did try nasm -fwin32
2.13.02 myself on my Linux desktop and got the same error.
An untested possible workaround might be to create a .obj
with a symbol definition for that absolute address, like
org 0deadbeefH
global my_target
my_target:
in NASM or however you do that in MASM.
Then in MASM or MSVC inline-asm you can use jmp my_target
and link with that .obj
. In theory that might work around the problem of representing relocations in the object file, and get the linker to calculate the relative branch displacement.