代码之家  ›  专栏  ›  技术社区  ›  Alex F

在Linux 64位中处理命令行[重复]

  •  4
  • Alex F  · 技术社区  · 14 年前

    我在从Linux64位汇编程序访问进程命令行时遇到问题。为了用最少的代码重现这一点,我制作了这个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位并在Linux64中运行时,它不会打印任何内容:

    .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 回复  |  直到 14 年前
        1
  •  10
  •   Matthew Slattery    14 年前

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

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

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


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

    • 使用 syscall 利息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
    
        2
  •  3
  •   Turbo J    14 年前

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

    这里有一个德语示例,对不起:
    http://zygentoma.de/codez/linux_assembler.php