我正在使用 nasm 进行 x86-64 汇编。我的任务是编写一个代码,接受一个数字作为命令行参数并将其转换为整数。使用 ld 链接器链接时,代码正常工作。但是如果使用 GCC 链接器,就会出现段错误。
这是我写的代码:
Projekat.asm:
%include "Macros.asm"
section .data
section .bss
section .text
global main
main:
mov rax, [rsp + 16] ; This line is used to store the second argument (which is the number)
; into rax register
call _convertToInt
newline ; newline, exit and rax are macros located in Macros.asm
exit
_convertToInt:
mov rdi, rax
mov rax, 0
_convertLoop:
movzx rcx, byte [rdi] ; By using GDB, I found out that Segfault occurs on this line!
cmp rcx, 0
je _end
sub rcx, 48
imul rax, 10
add rax, rcx
inc rdi
jmp _convertLoop
_end:
printValue rax
ret
宏.asm:
section .data
newline db 10, 0
newline_length equ $-newline
section .bss
digitSpace resb 100
digitSpacePos resb 8
%macro newline 0
mov rax, 1
mov rdi, 1
mov rsi, newline
mov rdx, 1
syscall
%endmacro
%macro exit 0
mov rax, 60
mov rdi, 0
syscall
%endmacro
%macro printValue 1
mov rax, %1
mov rcx, digitSpace
mov [digitSpacePos], rcx
%%printValLoop:
mov rdx, 0
mov rbx, 10
div rbx
mov r14, rax
add rdx, 48
mov rcx, [digitSpacePos]
mov [rcx], dl
inc rcx
mov [digitSpacePos], rcx
mov rax, r14
cmp rax, 0
jne %%printValLoop
%%printValFinalLoop:
mov rcx, [digitSpacePos]
mov rax, 1
mov rdi, 1
mov rsi, rcx
mov rdx, 1
syscall
mov rcx, [digitSpacePos]
dec rcx
mov [digitSpacePos], rcx
cmp rcx, digitSpace
jge %%printValFinalLoop
%endmacro
我正在使用 64 位 Ubuntu 20.04。以下是我使用的命令:
nasm -f elf64 -g -F dwarf Projekat.asm
ld -o Projekat Projekat.o
./Projekat 485
;在这种情况下,代码正常运行并打印数字!
但是,如果我使用 GCC 作为链接器,会发生这种情况:
nasm -f elf64 -g -F dwarf Projekat.asm
gcc Projekat.o -static -o Projekat
./Projekat 485
;导致段错误
我还使用了 backtrace 命令,这就是堆栈的样子:
#0 _convertLoop () at Projekat.asm:59
#1 0x0000000000401c0a in main () at Projekat.asm:13
我已经尝试解决这个问题 7 天了,如果有人知道段错误背后的问题是什么以及为什么代码在 ld 而不是 GCC 下正常工作,请告诉我。 提前感谢大家!
编辑:将 main 更改为 _start 可使代码与 ld 链接一起正常工作。但是,通过将 _start 更改为 main 并使用 gcc,代码不再有效。