nasm/ld "relocation truncated to fit: R_386_16"
<p>Assembly:</p>

<pre><code>[BITS 16]

global _start

_start:
    mov ax, 0x07C0
    mov ds, ax

    mov si, hw
    call print_string
    jmp $

print_string:
    mov ah, 0x0E
.char:
    lodsb
    cmp al, 0
    je .exit
    int 0x10
    jmp .char
.exit: ret

times 0x100-($-$$) db 0

hw: db "Hello, World!", 0

times 510-($-$$) db 0
dw 0xAA55
</code></pre>

<p>Assembling this with:</p>

<pre><code>$ nasm file.asm -felf -o file.o
</code></pre>

<p>And then linking it with:</p>

<pre><code>$ ld -melf_i386 -o file.bin file.o --oformat binary
</code></pre>

<p>Gives the following error:</p>

<pre><code>file.asm:(.text+0x6): relocation truncated to fit: R_386_16 against `.text'
</code></pre>

<p>After fiddling with the code a bit, i figured out that changing <code>mov si, hw</code> to <code>mov si, 0x100</code> works fine. But then what's the point of labels?</p>

<p>My guess is that ld can't generate 16 bits binary files, so it replaces <code>hw</code> with a 32 bit address instead of a 16 bit address. And then it complains because my program tries to put a 32 bit value into a 16 bit register.</p>

<p>Is there some argument i can pass to nasm/ld to make this work?</p>

<hr>

<p><strong>EDIT:</strong></p>

<p>elf doesn't support 16 bit, the only output format nasm supports wich actually states it supports 16 bit in <code>nasm -hf</code> is .obj, but i can't find a linker for it.</p>

<hr>

<p>NASM Manual:</p>

<blockquote>
  <p>The ELF32 specification doesn't provide relocations for 8- and 16-bit values, but the GNU ld linker adds these as an extension. NASM can generate GNU-compatible relocations, to allow 16-bit code to be linked as ELF using GNU ld. If NASM is used with the -w+gnu-elf-extensions option, a warning is issued when one of these relocations is generated.</p>
</blockquote>

<p>Adding <code>-w+gnu-elf-extensions</code> does indeed show a warning, but ld still gives the same error.</p>