从Linux 64位汇编程序访问进程命令行时遇到问题。 为了用最less的代码重现这一点,我制作了这个打印程序名称前5个字符的32位程序:
.section .text
.globl _start
_开始:
movl%esp,%ebp
movl $ 4,%eax#写入
movl $ 1,%ebx#stdout
movl 4(%ebp),%ecx#程序名称地址(argv [0])
movl $ 5,%edx#硬编码的长度
int $ 0x80
movl $ 1,%eax
movl $ 0,%ebx
int $ 0x80
这个程序正在工作。 当我将它翻译成64位并在Linux 64上运行时,它不会打印任何内容:
.section .text
.globl _start
_开始:
movq%rsp,%rbp
movq $ 4,%rax
movq $ 1,%rbx
movq 8(%rbp),%rcx#程序名称地址?
movq $ 5,%rdx
int $ 0x80
movq $ 1,%rax
movq $ 0,%rbx
int $ 0x80
我的错误在哪里?
编译器使用本地variables而不调整RSP
将值插入数组并显示,nasm
虚拟处理器和高级networkingLinux和Windows
Linux如何保护内存?
从组件中读取文件
在x86 nasm中分割时浮点exception
x86 – 获取方向标志(DF)的当前状态
在Windows中分析崩溃:错误消息告诉我们什么?
哪些寄存器在Linux的用户空间受到保护?
您正在将正确的地址加载到%rcx 。
int 0x80然后调用32位系统调用接口。 这将地址截断为32位,这使得它不正确。 (如果你使用一个调试器并在第一个int 0x80后面设置一个断点,你会发现它返回的时候是-14,在%eax中是-EFAULT 。)
第二个系统调用exit工作正常,因为截断到32位在这种情况下不会造成任何伤害。
如果要将64位地址传递给系统调用,则必须使用64位系统调用接口:
使用syscall ,而不是int 0x80 ;
使用不同的寄存器:见这里 ;
系统呼叫号码也不同:请参阅此处 。
这里是你的代码的工作版本:
.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位中使用不同的寄存器作为系统调用参数,为系统调用函数分配的编号也在i386和x86_64之间变化。
http://zygentoma.de/codez/linux_assembler.PHP
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。