重定位被截断以适应 r_386_8 对 .bss'
relocation truncated to fit r_386_8 against .bss'
当我尝试使用
将我的源构建为 Linux 的 32 位静态可执行文件时
nasm -f elf -F dwarf -g loop.asm
ld -m elf_i386 -o loop loop.o
我收到这个 R_386_8
错误,知道是什么原因造成的吗?
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
(编者注:此代码有多个错误;此问答主要是关于阻止它链接的错误。但修复该错误不会使 Linux 程序正常工作。)
在NASM中,$numA
与numA
相同。 A leading $
stops the assembler from considering it as a register name。因此,您可以编写 mov eax, [$eax]
从名为 eax
的符号加载 eax
寄存器。 (所以你可以 link 和使用 int eax = 123;
的 C)
所以 mov [$numA], al
看起来很奇怪,但它实际上只是 mov [numA], al
而不是错误的来源。
你从 mov dl,$numA
得到错误,它对地址的低字节执行 mov dl, imm8
。
大多数时候,这是 Basic use of immediates vs. square brackets in YASM/NASM x86 assembly 的情况 - 您打算从该地址的内存加载,例如 movzx edx, byte [numA]
或 mov dl, [numA]
。
linker 警告您,因为 numA
的地址不适合 1 个字节,因此 r_386_8
重定位必须截断地址。
_8
告诉你这是一个重定位,要求linker填写8位(1字节)作为绝对地址。 (8 位相对分支位移具有不同的重定位类型,尽管通常您会使用 32 位位移来跳转到另一个文件中的符号。)
r_386
告诉您这是一个 i386 重定位,而不是某种类型的 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(通用 ABI,i386 SysV psABI 是“处理器补充”)。
固定代码,注释以 ;*
开头,关于我修改了什么:
;* 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
当我尝试使用
将我的源构建为 Linux 的 32 位静态可执行文件时 nasm -f elf -F dwarf -g loop.asm
ld -m elf_i386 -o loop loop.o
我收到这个 R_386_8
错误,知道是什么原因造成的吗?
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
(编者注:此代码有多个错误;此问答主要是关于阻止它链接的错误。但修复该错误不会使 Linux 程序正常工作。)
在NASM中,$numA
与numA
相同。 A leading $
stops the assembler from considering it as a register name。因此,您可以编写 mov eax, [$eax]
从名为 eax
的符号加载 eax
寄存器。 (所以你可以 link 和使用 int eax = 123;
的 C)
所以 mov [$numA], al
看起来很奇怪,但它实际上只是 mov [numA], al
而不是错误的来源。
你从 mov dl,$numA
得到错误,它对地址的低字节执行 mov dl, imm8
。
大多数时候,这是 Basic use of immediates vs. square brackets in YASM/NASM x86 assembly 的情况 - 您打算从该地址的内存加载,例如 movzx edx, byte [numA]
或 mov dl, [numA]
。
linker 警告您,因为 numA
的地址不适合 1 个字节,因此 r_386_8
重定位必须截断地址。
_8
告诉你这是一个重定位,要求linker填写8位(1字节)作为绝对地址。 (8 位相对分支位移具有不同的重定位类型,尽管通常您会使用 32 位位移来跳转到另一个文件中的符号。)
r_386
告诉您这是一个 i386 重定位,而不是某种类型的 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(通用 ABI,i386 SysV psABI 是“处理器补充”)。
固定代码,注释以 ;*
开头,关于我修改了什么:
;* 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