【问题标题】:Process command line in Linux 64 bit [duplicate]Linux 64位中的进程命令行[重复]
【发布时间】:2011-04-13 09:42:14
【问题描述】:

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

.section .text .globl _start _开始: movl %esp, %ebp movl $4, %eax # 写入 movl $1, %ebx # 标准输出 movl 4(%ebp), %ecx # 程序名地址 (argv[0]) movl $5, %edx # 硬编码长度 诠释 $0x80 移动 $1, %eax 移动 $0, %ebx 诠释 $0x80

这个程序正在运行。当我将其翻译为 64 位并在 Linux 64 中运行时,它不会打印任何内容:

.section .text .globl _start _开始: movq %rsp, %rbp movq $4, %rax movq $1, %rbx movq 8(%rbp), %rcx # 程序名地址 ? movq $5, %rdx 诠释 $0x80 movq $1, %rax movq $0, %rbx 诠释 $0x80

我的错误在哪里?

【问题讨论】:

    标签: linux assembly 64-bit


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      您正在将正确的地址加载到%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
      

      【讨论】:

        猜你喜欢
        • 2018-12-08
        • 2011-11-18
        • 2016-12-03
        • 2013-05-27
        • 2011-04-10
        • 1970-01-01
        • 2014-08-10
        • 1970-01-01
        • 2011-07-06
        相关资源
        最近更新 更多