 <p>No answer yet has explained why NASM reports</p> <pre><code>Mach-O 64-bit format does not support 32-bit absolute addresses </code></pre> <p>The reason NASM won't do this is explained in <a href="http://agner.org/optimize/optimizing_assembly.pdf" rel="nofollow">Agner Fog's Optimizing Assembly</a> manual in section <em>3.3 Addressing modes</em> under the subsection titled <em>32-bit absolute addressing in 64 bit mode</em> he writes</p> <blockquote> <p>32-bit absolute addresses cannot be used in Mac OS X, where addresses are above 2^32 by default.</p> </blockquote> <p>This is not a problem on Linux or Windows. In fact I already showed this works at <a href="http://stackoverflow.com/questions/26358119/static-linkage-with-glibc-without-calling-main">static-linkage-with-glibc-without-calling-main</a>. That hello world code uses 32-bit absolute addressing with elf64 and runs fine.</p> <p>@HristoIliev suggested using rip relative addressing but did not explain that 32-bit absolute addressing in Linux would work as well. In fact if you change <code>lea rdi, [rel msg]</code> to <code>lea rdi, [msg]</code> it assembles and runs fine with <code>nasm -efl64</code> but fails with <code>nasm -macho64</code></p> <p>Like this:</p> <pre><code>section .data msg db 'This is a test', 10, 0 ; something stupid here section .text global _main extern _printf _main: push rbp mov rbp, rsp xor al, al lea rdi, [msg] call _printf mov rsp, rbp pop rbp ret </code></pre> <p>You can check that this is an absolute 32-bit address and not rip relative with <code>objdump</code>. However, it's important to point out that the preferred method is still rip relative addressing. Agner in the same manual writes:</p> <blockquote> <p>There is absolutely no reason to use absolute addresses for simple memory operands. Rip- relative addresses make instructions shorter, they eliminate the need for relocation at load time, and they are safe to use in all systems.</p> </blockquote> <p>So when would use use 32-bit absolute addresses in 64-bit mode? Static arrays is a good candidate. See the following subsection <em>Addressing static arrays in 64 bit mode</em>. The simple case would be e.g:</p> <pre><code>mov eax, [A+rcx*4] </code></pre> <p>where A is the absolute 32-bit address of the static array. This works fine with Linux but once again you can't do this with Mac OS X because the image base is larger than 2^32 by default. To to this on Mac OS X see example 3.11c and 3.11d in Agner's manual. In example 3.11c you could do</p> <pre><code>mov eax, [(imagerel A) + rbx + rcx*4] </code></pre> <p>Where you use the extern reference from Mach O <code>__mh_execute_header</code> to get the image base. In example 3.11c you use rip relative addressing and load the address like this</p> <pre><code>lea rbx, [rel A]; rel tells nasm to do [rip + A] mov eax, [rbx + 4*rcx] ; A[i] </code></pre>