Mac x86_64环境下nasm汇编实现文件操作功能失效如何解决
macOS x64 NASM 创建文件并写入Hello World实现方案
你代码的核心错误点
- 参数顺序搞反:open系统调用第一个参数rdi是文件路径指针,第二个参数rsi是打开模式,你前几版把模式和路径的位置搞反了
- 未使用open返回的文件描述符:open调用成功后返回值存在rax中,这是后续write、close操作需要用到的唯一文件标识,不能硬编码3、1或者传路径字符串给close
- 缺少创建文件必须的标志位:要创建新文件需要给open加上
O_CREAT标志,同时指定新文件的访问权限 - write调用目标错误:之前写的rdi=1是向标准输出写,要写入文件需要传入open返回的文件描述符
- close参数错误:close系统调用仅需要传入文件描述符作为唯一参数,不需要传文件路径、长度等其他参数
- 文件路径未加0终止符:传入open的路径必须是C风格的0结尾字符串,你之前的file定义没有加结尾的0,会导致系统识别路径错误
对应C语言fclose的汇编实现
C标准库的fclose(FILE* fp)底层封装的是系统调用close,如果你直接使用open系统调用,直接把open返回的文件描述符传入close的rdi寄存器即可:
; 假设rax里存的是open返回的文件描述符 mov rdi, rax mov rax, 0x2000006 syscall
如果是调用C标准库的fopen得到的FILE指针,需要先从FILE结构体偏移位置取出对应的文件描述符再调用close,或者直接调用C标准库的fclose函数即可。
完整可运行代码
global start section .text start: ; open系统调用:创建/打开test.txt ; 调用号:0x2000005 ; 参数:rdi=文件路径, rsi=打开模式, rdx=文件权限 mov rax, 0x2000005 mov rdi, file ; 第一个参数:文件路径指针 mov rsi, 0x601 ; 第二个参数:O_WRONLY | O_CREAT | O_TRUNC,不存在就创建,存在就清空内容只写 mov rdx, 0o644 ; 第三个参数:新文件权限,用户读写、组和其他用户只读 syscall ; 调用成功后rax里存的是文件描述符 mov r12, rax ; 把文件描述符保存到r12寄存器,避免被后续调用覆盖 ; write系统调用:写入Hello World到文件 ; 调用号:0x2000004 ; 参数:rdi=文件描述符, rsi=写入内容指针, rdx=写入长度 mov rax, 0x2000004 mov rdi, r12 ; 第一个参数:前面open得到的文件描述符 mov rsi, str ; 第二个参数:要写入的字符串指针 mov rdx, strlen ; 第三个参数:字符串长度 syscall ; close系统调用:关闭文件 ; 调用号:0x2000006 ; 参数:rdi=要关闭的文件描述符 mov rax, 0x2000006 mov rdi, r12 ; 第一个参数:要关闭的文件描述符 syscall ; exit系统调用:退出程序 mov rax, 0x2000001 xor rdi, rdi syscall section .data str db "Hello World", 0xA ; 加个换行,可选 strlen equ $ - str file db "test.txt", 0 ; 文件路径要以0结尾,符合C字符串规范 lenfile equ $ - file
编译运行命令
# 汇编生成macho64格式目标文件 nasm -f macho64 hello.asm -o hello.o # 链接生成可执行文件,指定入口为start,指定macOS版本避免警告 ld hello.o -o hello -e start -macosx_version_min 10.15 # 运行 ./hello
运行后会在当前目录生成test.txt文件,内容为Hello World。
内容的提问来源于stack exchange,提问作者Yoffdan
相关产品推荐
相关产品推荐

