Linux 64位进程命令行

时间:2010-09-16 19:29:36

标签: linux assembly 64-bit

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

.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

我的错误在哪里?

2 个答案:

答案 0 :(得分:10)

您正在将正确的地址加载到%rcx

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

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


如果要将64位地址传递给系统调用,则必须使用64位系统调用接口:

  • 使用syscall,而不是int 0x80;
  • 使用了不同的寄存器:请参阅here;
  • 系统电话号码也不同:请参阅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

答案 1 :(得分:3)

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

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