When I try to build my source into a 32-bit static executable for Linux with
nasm -f elf -F dwarf -g loop.asm
ld -m elf_i386 -o loop loop.o
I get this R_386_8
error, any idea what causes it?
foo.o: in function `loop1':
foo.asm:(.text+0x12): relocation truncated to fit: R_386_8 against `.bss'
foo.o: in function `endend':
foo.asm:(.text+0x2f): relocation truncated to fit: R_386_8 against `.bss'
loop.asm
cr equ 13
lf equ 10
section .bss
numA resb 1
section .text
global _start:
mov [numA],byte 0
call loop1
jmp endend
loop1:
xor cx,cx
mov al, $numA
cmp cx, 0x0A
jle else
inc al
jmp end
else:
dec al
jmp end
end:
mov [$numA], al
inc cx
cmp cx,20
jle loop1
endend:
mov dl,$numA
mov ah,2
int 21h ; note: DOS system calls won't work in Linux
(Editor's note: this code has multiple bugs; this Q&A is primarily about the one preventing it from linking. But fixing that won't make a working Linux program.)
In NASM, $numA
is the same as numA
. A leading $
stops the assembler from considering it as a register name. Thus you can write mov eax, [$eax]
to load the eax
register from a symbol called eax
. (So you could link with C which used int eax = 123;
)
So mov [$numA], al
looks weird, but it's really just mov [numA], al
and isn't the source of the error.
You're getting the error from mov dl,$numA
which does a mov dl, imm8
of the low byte of the address.
Most times, that's a case of Basic use of immediates vs. square brackets in YASM/NASM x86 assembly - where you meant to load from memory at that address, like movzx edx, byte [numA]
or mov dl, [numA]
.
The linker warns you because the address of numA
doesn't fit in 1 byte, so the r_386_8
relocation would have had to truncate the address.
The _8
tells you it's a relocation that asks the linker to fill in 8 bits (1 byte) as an absolute address. (8-bit relative branch displacements have a different relocation type, although normally you'd use a 32-bit displacement for jumping to a symbol in another file.)
The r_386
tells you it's an i386 relocation as opposed to some type of r_x86_64
relocation (which could be absolute or RIP-relative), or a MIPS jump-target relocation (which would need to right-shift the offset by 2). Possibly related: Relocations in the System V gABI (generic ABI, for which the i386 SysV psABI is a "processor supplement").