重定位被截断以适应r_386_8对抗.bss'

时间:2017-10-25 09:19:55

标签: assembly nasm ld

当我输入ld -m elf_i386 -o loop 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

2 个答案:

答案 0 :(得分:2)

在NASM中,$numAnumA相同。 A leading $ stops the assembler from considering it as a register name。因此,您可以编写mov eax, [$eax]以从名为eax的符号加载eax寄存器。 (所以你可以用C语言链接int eax = 123;

所以mov [$numA], al看起来很奇怪,但它只是mov [numA], al而不是警告的来源。

您正在收到来自mov dl,$numA的警告,该警告执行地址低位字节的mov dl, imm8

链接器会向您发出警告,因为numA的地址不适合1个字节,因此r_386_8重定位会截断地址。

_8告诉您它是一个重定位,要求链接器填写8位。 r_386告诉你它是一个i386重定位,而不是某种类型的r_x86_64重定位(可能是绝对的或RIP相关的),或MIPS跳转目标重定位(需要它)将偏移右移2)。可能相关:Relocations in the System V gABI(通用ABI,其中i386 SysV psABI是"处理器补充")。

答案 1 :(得分:0)

带有关于我修改内容的;*评论的固定代码:

;* 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

运行之后:

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

预期输出:

255