Linux中的进程命令行64位

问题描述:

从Linux 64位汇编程序访问进程命令行时遇到问题。为了用最少的代码重现此,我在此32位程序打印出节目名称的前5个字符:Linux中的进程命令行64位

 
.section .text 

.globl _start 
_start: 
movl %esp, %ebp 

movl $4, %eax  # write 
movl $1, %ebx  # stdout 
movl 4(%ebp), %ecx # program name address (argv[0]) 
movl $5, %edx  # hard-coded length 
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  # program name address ? 
movq $5, %rdx 
int $0x80 

movq $1, %rax 
movq $0, %rbx 
int $0x80 

我的错误在哪里?

您正在加载正确的地址为%rcx

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

第二个系统调用,exit,工程确定,因为截断至32在这种情况下位不会造成任何伤害。


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

  • 使用syscall,不int 0x80;使用不同的寄存器:
  • 系统调用号码也不同:请参阅here

这里是你的代码的工作版本:

.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 

正如在X86_64 ABI中所述:使用syscall指令而不是int $0x80。内核在64位中使用不同的寄存器作为系统调用参数,为syscall函数分配的编号也在i386和x86_64之间变化。

一个例子 - 在德国,对不起 - 可以在这里找到:
http://zygentoma.de/codez/linux_assembler.php