1

I'm writing a basic hello world program in x86_64 GNU Assembly on Windows. Since I could not find a working example for Windows, I've been following a tutorial for Linux, replacing the syscalls with Windows kernel32 calls.

The person in the tutorial is using leaq to load the address of a string to be printed, when I try this, I get a linking error relocation truncated to fit: R_X86_64_32S against '.rodata'. If I try to load the string with movabsq instead, which I found by googling that error above, the program links and runs correctly.

This is the assembly with leaq (not working):

.extern GetStdHandle
.extern WriteFile
.extern ExitProcess

.global _start

.section .rodata

msg: .ascii "Hello World!\n"

.section .text

_start:
  # stdout = GetStdHandle(-11)
  movq $-11, %rcx
  call GetStdHandle

  # WriteFile(stdout, msg, 13, 0, 0)
  movq %rax, %rcx
  leaq msg, %rdx
  movq $13, %r8
  movq $0, %r9
  push $0
  call WriteFile

  # ExitProcess(0)
  xor %rcx, %rcx
  call ExitProcess

This is the assembly with movabsq (working):

.extern GetStdHandle
.extern WriteFile
.extern ExitProcess

.global _start

.section .rodata

msg: .ascii "Hello World!\n"

.section .text

_start:
  # stdout = GetStdHandle(-11)
  movq $-11, %rcx
  call GetStdHandle

  # WriteFile(stdout, msg, 13, 0, 0)
  movq %rax, %rcx
  movabsq $msg, %rdx
  movq $13, %r8
  movq $0, %r9
  push $0
  call WriteFile

  # ExitProcess(0)
  xor %rcx, %rcx
  call ExitProcess

Why is my program not linking with leaq like it did in the tutorial? What is the difference between leaq and movabsq?

Thanks in advance!

Oliver
  • 11
  • 1
  • `lea` can use RIP-relative addressing to load a single address, which no form of `mov` can do. I don't know how to get gas to emit this though. – ecm Aug 31 '23 at 09:02
  • 1
    You used LEA with an absolute addressing mode, not `msg(%rip)`, so its only choice was a `disp32` absolute address. Never do that. If you want to use 32-bit absolute addresses for symbols (in a non-PIE executable), use `mov $msg, %edx` (32-bit operand-size for a 5-byte instruction). And if your address won't fit in a 32-bit absolute, do something else, preferably RIP-relative LEA. See the linked duplicate. (@ecm) – Peter Cordes Aug 31 '23 at 09:34
  • I think you want `.rdata` as a section name on Windows. I'm not sure if that varies by toolchain (MASM vs. NASM/GAS), or by ABI or object-file format (COFF / PE-32+ vs. ELF). I'm also surprised to see a `_start` symbol here rather than `WinMain` or something, but maybe GNU `ld` will look for `_start` when linking a Windows executable the same as when linking for Linux. – Peter Cordes Aug 31 '23 at 09:39
  • @PeterCordes after reading through the answer on the linked question I replaced the `leaq msg, %rdx` with `leaq msg(%rip), %rdx`. Am I understanding correctly that the RIP addressing converts my address (which for some reason is 32bit) to a 64bit number that would fit the register? – Oliver Aug 31 '23 at 10:02
  • 1
    RIP (the program counter) is a 64-bit register. RIP + a 32-bit relative displacement produces a 64-bit absolute address. [How do RIP-relative variable references like "\[RIP + \_a\]" in x86-64 GAS Intel-syntax work?](https://stackoverflow.com/q/54745872) also covers AT&T syntax, and what it actually means in machine code. – Peter Cordes Aug 31 '23 at 10:16
  • 1
    Also I guess [Why does this MOVSS instruction use RIP-relative addressing?](https://stackoverflow.com/q/44967075) for more background about why RIP-relative addressing is always used for static data, and for function pointers. (And `call foo` is also `call rel32`, so relative jumps / calls have the same reach of +-2GiB as RIP-relative data addressing.) – Peter Cordes Aug 31 '23 at 10:24
  • My answer on [How to load address of function or label into register](https://stackoverflow.com/q/57212012) did link those 2 Q&As, so IDK if you have any suggestions on where I could put that info to help other future readers no miss it, but without cluttering things up too much. If you think of anything I could edit, let me know. – Peter Cordes Aug 31 '23 at 10:28
  • @PeterCordes thanks! all these links are very helpful and will be great learning. And sorry, I'm not familiar with Stack Overflow, so I can't comment on the suggestions – Oliver Aug 31 '23 at 11:10
  • I meant in terms of edits to my answer on that question, since that was the first thing I pointed you at, but I guess those links weren't presented as interesting enough or as things that would answer related questions about what RIP-relative addressing even is. I'd hoped that beginners like yourself would see those links and get more of a complete picture, and I'm wondering if there's any way I could improve that answer for future beginners with the same question. So if you have any ideas, e.g. phrasing that would catch your attention given what you didn't know at the time, let me know. – Peter Cordes Aug 31 '23 at 23:52

0 Answers0