在Linux 64位系统中处理命令行

5
我有问题访问Linux 64位汇编程序的进程命令行。为了用最少的代码重现这个问题,我写了一个32位程序,它打印程序名称的前5个字符:
.section .text
.globl _start _start: movl %esp, %ebp movl $4, %eax # 写入 movl $1, %ebx # 标准输出 movl 4(%ebp), %ecx # 程序名地址 (argv[0]) movl $5, %edx # 硬编码长度 int $0x80
movl $1, %eax movl $0, %ebx int $0x80
这个程序是工作的。当我将其转换为64位并在Linux 64中运行时,它没有打印任何东西:
.section .text
.globl _start _start: movq %rsp, %rbp movq $4, %rax movq $1, %rbx movq 8(%rbp), %rcx # 程序名地址 ? movq $5, %rdx int $0x80
movq $1, %rax movq $0, %rbx int $0x80
我的错误在哪里?
2个回答

10

你将正确的地址加载到了%rcx寄存器中。

int 0x80会调用32位系统调用接口,这将地址截断为32位,导致地址不正确。(如果你使用调试器,在第一个int 0x80后设置断点,你会看到它返回%eax中的-14(即-EFAULT))。

第二个系统调用exit正常工作,因为在这种情况下截断64位地址不会造成伤害。


如果你想将一个64位地址传递给系统调用,你将需要使用64位系统调用接口:

  • 使用syscall而不是int 0x80
  • 使用不同的寄存器:参见这里
  • 系统调用号也不同:参见这里

这里是一个可工作的版本:

.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

3
根据X86_64 ABI所述:使用syscall指令代替int $0x80。内核在64位中使用不同的寄存器作为syscall参数,并且分配给syscall函数的编号也因i386和x86_64而异。这里有一个例子 - 德语的,抱歉 - 可以在此处找到:
http://zygentoma.de/codez/linux_assembler.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接