Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 981
Peter Cordes Avatar asked Nov 08 '22 07:11

Peter Cordes


1 Answers

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.

like image 63
Peter Cordes Avatar answered Nov 15 '22 13:11

Peter Cordes