x64 AT&T汇编open系统调用返回EFAULT错误求助
问题分析与修复方案
核心问题原因
- 误用32位系统调用入口:x64架构下Linux必须使用
syscall指令触发系统调用,int $0x80是32位兼容接口,会强制截断寄存器为32位,导致内核无法正确解析64位地址,直接触发EFAULT错误。 - 系统调用号与寄存器规则不匹配:32位open调用号是5,但x64下系统调用号、参数传递寄存器完全不同——x64要求:
- rax 存储系统调用号
- rdi 第一个参数(文件路径指针)
- rsi 第二个参数(打开标志)
- rdx 第三个参数(权限,仅O_CREAT生效)
- 第四个参数用r10
- 文件名指针获取逻辑错误:你试图从
16(%rbp)读取文件名,但该位置是命令行参数argv[1]的地址,而非你定义的filePath地址,完全偏离目标。 - 变量长度不兼容:
fileHandle定义为4字节,但x64下文件句柄是8字节整数,长度不足会导致数据截断。
修复后的代码示例
.section .bss .lcomm fileBuffer, 50 .lcomm fileHandle, 8 # 适配x64 8字节句柄 .section .data filePath: .asciz "test.txt" # x64标准系统调用定义 OPENAT: .quad 257 # openat调用号(推荐替代直接open) AT_FDCWD: .quad -100 # 代表当前工作目录 OPEN_FLAGS: .quad 0102 # O_WRONLY | O_CREAT(八进制) OPEN_PERMS: .quad 0444 # 文件权限(仅O_CREAT时生效) .section .text .globl _start _start: # 准备openat系统调用参数 movq AT_FDCWD, %rdi # 第一个参数:当前目录句柄 movq $filePath, %rsi # 第二个参数:目标文件路径 movq OPEN_FLAGS, %rdx # 第三个参数:打开模式 movq OPEN_PERMS, %r10 # 第四个参数:文件权限 movq OPENAT, %rax # 系统调用号存入rax syscall # 触发x64系统调用 # 错误检查 test %rax, %rax js badfile # 若rax为负数(错误码),跳转到错误处理 # 正常流程代码(省略) # ... badfile: # 错误退出示例 movq $60, %rax # x64 exit系统调用号 movq $1, %rdi # 退出码1 syscall
后续诊断方向
- 用
gdb调试:在syscall指令处打断点,查看rdi寄存器是否指向filePath的正确地址,确认参数传递无误。 - 验证文件路径:确保
test.txt存在于程序运行的当前工作目录,或改用绝对路径测试排除路径问题。 - 编译运行检查:使用
as -o test.o test.s && ld -o test test.o编译,运行前用pwd确认当前目录。
内容的提问来源于stack exchange,提问作者200817189a
相关产品推荐
相关产品推荐

