在 Linux 64 位中处理命令行 [英] Process command line in Linux 64 bit
问题描述
我在从 Linux 64 位汇编程序访问进程命令行时遇到问题.为了用最少的代码重现这一点,我制作了这个 32 位程序,它打印程序名称的前 5 个字符:
<前>.section .text.globl _start_开始:movl %esp, %ebpmovl $4, %eax # 写movl $1, %ebx # 标准输出movl 4(%ebp), %ecx #程序名地址(argv[0])movl $5, %edx # 硬编码长度整数 $0x80movl $1, %eaxmovl $0, %ebx整数 $0x80这个程序正在运行.当我将其转换为 64 位并在 Linux 64 中运行时,它不打印任何内容:
<前>.section .text.globl _start_开始:movq %rsp, %rbpmovq $4,%raxmovq $1, %rbxmovq 8(%rbp), %rcx # 程序名称地址?movq $5,%rdx整数 $0x80movq $1, %raxmovq $0, %rbx整数 $0x80我的错误在哪里?
您正在将正确的地址加载到 %rcx
中.
int 0x80
然后调用 32 位系统调用接口.这会将地址截断为 32 位,从而使其不正确.(如果您使用调试器并在第一个 int 0x80
之后设置断点,您将看到它在 %eax
中返回 -14,即 -EFAULT
.)
第二个系统调用 exit
工作正常,因为在这种情况下截断为 32 位不会造成任何伤害.
如果要将 64 位地址传递给系统调用,则必须使用 64 位系统调用接口:
这是您的代码的工作版本:
.section .text.globl _start_开始:movq %rsp, %rbpmovq $1, %raxmovq $1, %rdimovq 8(%rbp), %rsi # 程序名称地址?movq $5,%rdx系统调用movq 60 美元,%raxmovq $0, %rdi系统调用
I have problems accessing the process command line from Linux 64 bit Assembly program. To reproduce this with minimal code, I made this 32-bit program which prints first 5 characters of the program name:
.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
This program is working. When I translate it to 64 bit and run in Linux 64, it doesn't print anything:
.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
Where is my mistake?
You are loading the correct address into %rcx
.
int 0x80
then invokes the 32-bit syscall interface. That truncates the address to 32 bits, which makes it incorrect. (If you use a debugger and set a breakpoint just after the first int 0x80
, you will see that it returns with -14 in %eax
, which is -EFAULT
.)
The second syscall, exit
, works OK because the truncation to 32 bits doesn't do any harm in that case.
If you want to pass a 64-bit address to a system call, you will have to use the 64-bit syscall interface:
- use
syscall
, notint 0x80
; - different registers are used: see here;
- the system call numbers are different as well: see here.
Here is a working version of your code:
.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
这篇关于在 Linux 64 位中处理命令行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!