我正在尝试用汇编语言编写一个简单的程序,它将写出程序的名称。使用 gdb 进行调试,我确定对 sys_write 的调用返回 -14 (EFAULT)。我还能够验证我的 strlen 函数是否正常工作。似乎存在某种内存访问问题,但鉴于 strlen 正在访问相同的内存并且工作正常,我不明白可能出了什么问题。出了什么问题?
谢谢!
完整代码:
section .text
global _start
_start:
mov rax, [rsp+8]
push rax
call strlen
add rsp, 8
mov rdx, rax ; bytes to write
mov rax, 4 ; sys_write
mov rbx, 1 ; stdout
mov rcx, [rsp+8] ; addr of string
int 0x80
; exit
mov rax, 1
mov rbx, 0
int 0x80
strlen:
mov rax, 0
mov rbx, [rsp+8]
strlen_loop:
cmp byte [rbx+rax], 0
je strlen_end
inc rax
jmp strlen_loop
strlen_end:
ret ; len in rax
最佳答案
正如我在评论中所写,x86_64 使用与 32 位 linux 不同的系统调用方法。特别是 int $0x80
不再是执行此操作的方法(尽管如果安装了 32 位库,它可能会半工作......)。参见例如这个 previous discussion .
在 32 位 x86 上你会做什么:
mov eax, SYSCALL_NUMBER
mov ebx, first_param
mov ecx, second_param
mov edx, third_param
int 0x80
您应该在 x86_64 上执行以下操作:
mov rax, SYSCALL_NUMBER_64 ; This is usually different from the 32-bit version!
mov rdi, first_param
mov rsi, second_param
mov rdx, third_param
syscall
要打印程序名称,请将您的程序更改为以下内容,它应该可以工作。对于其他对启动时程序环境的外观感兴趣的人,请参阅 here .
section .text
global _start
_start:
mov rax, [rsp+8]
push rax
call strlen
add rsp, 8
mov rdi, 1 ; fd = stdout
mov rsi, [rsp+8] ; buf = addr to string
mov rdx, rax ; count = strlen(string)
mov rax, 1 ; write
syscall
mov rdi, 0 ; status = 0
mov rax, 60 ; exit
syscall
strlen:
mov rax, 0
mov rbx, [rsp+8]
strlen_loop:
cmp byte [rbx+rax], 0
je strlen_end
inc rax
jmp strlen_loop
strlen_end:
ret ; len in rax
编译使用:
nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o
关于assembly - 学习汇编——回显程序名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7006926/