我从Linux 64位汇编程序访问进程命令行时遇到问题。为了用最少的代码重现该代码,我制作了一个32位程序,该程序打印程序名的前5个字符:
.section .text .globl _开始 _开始: move%esp,%ebp movl $ 4,%eax#写 movl $ 1,%ebx#stdout movl 4(%ebp),%ecx#程序名称地址(argv [0]) movl $ 5,%edx#硬编码长度 整数$ 0x80 movl $ 1,%eax movl $ 0,%ebx 整数$ 0x80
该程序正在运行。当我将其转换为64位并在Linux 64上运行时,它不会显示任何内容:
.section .text .globl _开始 _开始: movq%rsp,%rbp movq $ 4,%rax movq $ 1,%rbx movq 8(%rbp),%rcx#程序名称地址 movq $ 5,%rdx 整数$ 0x80 movq $ 1,%rax movq $ 0,%rbx 整数$ 0x80
我的错误在哪里?
您正在将正确的地址加载到中%rcx。
%rcx
int 0x80然后调用32位syscall接口。这会将地址截断为32位,这使它不正确。(如果您使用调试器并在第一个调试器之后设置一个断点int 0x80,则会看到它返回-14 in %eax,即-EFAULT。)
int 0x80
%eax
-EFAULT
第二个syscall exit可以正常工作,因为在这种情况下,截断为32位不会造成任何损害。
exit
如果要将64位地址传递给系统调用,则必须使用64位syscall接口:
syscall
这是您的代码的有效版本:
.section .text .globl _start _start: movq %rsp, %rbp movq $1, %rax movq $1, %rdi movq 8(%rbp), %rsi # program name address ? movq $5, %rdx syscall movq $60, %rax movq $0, %rdi syscall