NASM调用syscall write时使用栈作为数据源无输出问题求助
问题成因分析
核心原因:混用了64位寄存器与32位系统调用接口
你遇到的问题本质是x86_64架构下32位兼容系统调用int 0x80的地址限制导致的,具体分两点:
int 0x80是32位Linux原生的系统调用接口,在64位运行环境下,内核只会处理低于0xFFFFFFFF的32位地址空间的指针参数,同时只会读取寄存器的低32位作为参数值。- x86_64 Linux的用户态栈默认映射到远高于0xFFFFFFFF的高地址区间,你将栈指针
rsp赋值给rcx作为缓冲区地址传入时,int 0x80会直接截断rcx的高32位,得到的非法地址无法被内核访问,write系统调用执行失败,自然没有输出。 - 你第一个示例能正常运行,是因为
text标签指向的静态字符串位于低地址的代码段,截断低32位后地址仍然有效,所以没有触发问题。
修复方案
两种方案任选其一即可:
方案1:改用64位原生系统调用指令syscall
64位系统调用没有地址限制,参数寄存器约定和32位不同,对应修改后的代码如下:
global _start section .text _start: mov rcx, 0x0a47464544434241 push rcx mov rsi, rsp ; 64位write第2个参数:缓冲区地址存rsi mov rdx, 7 ; 第3个参数:输出长度 mov rdi, 1 ; 第1个参数:stdout文件描述符1 mov rax, 1 ; 64位write系统调用号为1 syscall mov rax, 60 ; 64位exit系统调用号为60 mov rdi, 0 syscall
编译运行即可正常输出ABCDEFG。
方案2:编译为32位程序
如果你要保留int 0x80的写法,编译时指定32位目标格式即可,32位程序的栈地址落在32位地址空间范围内,不会被截断:
nasm -f elf32 your_code.asm -o test.o ld -m elf_i386 test.o -o test
运行生成的32位可执行文件即可正常输出。
内容的提问来源于stack exchange,提问作者0ok3rn3lp4n1co0
相关产品推荐
相关产品推荐

