relocation truncated to fit r_386_8 against .bss'

后端 未结 2 1599
轮回少年
轮回少年 2020-12-18 13:08

When i type ld -m elf_i386 -o loop loop.asm, i get the error stated in the title, any idea what causes it? Sorry if the code looks bad, fairly new to assembly.



        
相关标签:
2条回答
  • 2020-12-18 13:48

    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.

    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").

    0 讨论(0)
  • 2020-12-18 13:54

    The fixed code with comments starting ;* about what did I modify:

    ;* build commands used to test:
    ;* nasm -f elf32 -F dwarf -g loop.asm -l loop.lst -w+all
    ;* ld -m elf_i386 -o loop loop.o
    
    cr equ 13
    lf equ 10
    
    section .bss
    numA resb 1
    
    section .text
    
    global _start   ;* global directive takes symbol name (without colon)
    
    _start:
    ;* the actual label you defined as global, and want to start from.
    
        ;* set memory at numA address to byte zero
        mov [numA],byte 0
        ;* try to call subroutine with loop
        call loop1
        jmp endend
    
    loop1:
        xor cx,cx       ;* loop counter = 0
    .real_loop: 
    ;* you don't want to loop to "loop1" as that will reset CX!
        mov al, [$numA] ; load AL with value from memory at numA address
    ;* in NASM you must use [] to indicate memory load/store
    ;* the mov al, $numA tried to put the memory address numA into AL
    ;* but memory address in x86-32 is 32 bit value, and AL is 8 bit only
    ;* and you didn't want address, but value any way.
        cmp cx, 0x0A
        jle .else 
        inc al
        jmp .end
    .else:
    ;* I modified all subroutine labels to be "local" starting with dot
    ;* i.e. ".else" is full label "loop1.else". This practice will allow
    ;* you to use also ".else" in different subroutines, while global
    ;* "else:" can be used only once per source file.
        dec al
        jmp .end
    .end:
        mov [$numA], al
        inc cx
        cmp cx,20
        jle .real_loop      ;* fix of loop jump (to not reset CX)
        ;* after CX will reach value 21, the CPU will continue here
        ret         ;* so added return from subroutine
    
    endend:
        ;* call linux 32b sys_exit(numA value) to terminate
        ;* return value will be equal to zero-extended [numA] to 32bits
        ;* 8bit -1 = 0xFF -> return value is 255
        movzx   ebx,byte [$numA]
        mov     eax,1
        int     80h
    

    After running this:

    nasm -f elf32 -F dwarf -g loop.asm -l loop.lst -w+all
    ld -m elf_i386 -o loop loop.o
    ./loop ; echo $?
    

    The output is expected:

    255
    
    0 讨论(0)
提交回复
热议问题