Assembly 学习程序集-echo程序名
我试图在汇编中编写一个简单的程序,它将写出程序名。使用gdb进行调试,我确定对sys_write的调用返回-14(EFAULT)。我还能够验证strlen函数是否正常工作。似乎存在某种内存访问问题,但鉴于斯特伦正在访问相同的内存并且工作正常,我不明白会有什么错误。出什么事了 谢谢 完整代码:Assembly 学习程序集-echo程序名,assembly,x86-64,Assembly,X86 64,我试图在汇编中编写一个简单的程序,它将写出程序名。使用gdb进行调试,我确定对sys_write的调用返回-14(EFAULT)。我还能够验证strlen函数是否正常工作。似乎存在某种内存访问问题,但鉴于斯特伦正在访问相同的内存并且工作正常,我不明白会有什么错误。出什么事了 谢谢 完整代码: section .text global _start _start: mov rax, [rsp+8] push rax call strlen add rsp,
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
在开始处添加带有8的rsp,导致
sys\u write
调用获得strlen函数之外的另一个字符串。strlen
不会改变堆栈,并且以后不会使用推送的rax
?为什么不删除push-rax
和add-rsp,8
语句,看看这对您来说是如何工作的呢?正如我在评论中所写的,x86_64对系统调用使用的方法与32位linux不同。尤其是int$0x80
不再是实现这一点的方法(尽管如果您安装了32位库,它可能会半工作……)。例如,请参见
在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
要打印程序名,请将您的程序更改为以下内容,它应该可以工作。对于其他对程序环境在启动时的外观感兴趣的人,请参阅
使用以下方式编译:
nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o
尝试在调试器中逐行检查此参数,以验证sys_write的参数是否正确?是的,我在第一个int 0x80处停止执行,并验证所有参数是否正确。我在gdb中使用了x/s$rcx,以确保实际上存在一个我认为应该存在的字符串。在x86_64上,
int$0x80
不用于syscall(并且syscall编号已更改),请参阅前面的许多讨论之一,例如add rsp,8
是对\uu cdecl
调用strlen
的堆栈清理,其中使用了“pushed rax”。。。
nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o