Windows 64位NASM文件读写异常:文件创建后为空无法写入
文件创建后无法写入的问题修复
问题描述
文件已创建但无法写入,程序执行到写入阶段时略有卡顿,预期生成包含内容的文件,但实际生成的是空文件。
原代码
DEFAULT REL global main extern CreateFileA extern CloseHandle extern WriteFile section .data filename db "f.txt", 0 section .text main: sub rsp, 48h mov rcx, filename mov dword [rsp+40], 40000000h | 2 xor r9d, r9d xor r8d, r8d mov dword [rsp+32], 2 mov edx, 2 сall CreateFileA mov rdx, rax mov rcx, rdx lea rdx, [filename] mov r8, 6 mov r9, 0 call WriteFile mov rcx, rdx call CloseHandle xor eax,eax add rsp, 48h ret
错误分析与修复
1. 语法与调用约定错误
- 替换俄文
с为英文c:原代码中сall CreateFileA的с是俄文字符,会导致汇编器识别失败,需改为标准英文指令call。 - 修正CreateFileA参数布局:Windows x64调用约定要求前4个参数用
RCX、RDX、R8、R9传递,剩余参数从右往左放入栈中(栈需16字节对齐)。原代码参数位置完全混乱,正确的参数对应:RCX:文件名(原代码正确)RDX:访问权限,设为GENERIC_WRITE即40000000hR8:共享模式,设为FILE_SHARE_WRITE即2R9:安全属性,设为NULL即0[rsp+32]:创建方式,设为CREATE_ALWAYS即2[rsp+40]:文件属性,设为FILE_ATTRIBUTE_NORMAL即80h- 原代码中
mov dword [rsp+40], 40000000h | 2的位或操作不符合汇编语法,需直接使用合并后的值40000002h或提前用or指令计算。
2. WriteFile参数缺失与句柄丢失
- 补充第五个参数:Windows x64下调用WriteFile必须显式传入第五个参数(重叠结构指针),即使设为
NULL也要放在[rsp+32]位置,否则会栈不平衡导致调用失败。 - 保护文件句柄:原代码将CreateFileA返回的句柄存在
RDX,但WriteFile调用时RDX被用作缓冲区参数,导致后续CloseHandle传入的是缓冲区地址而非句柄,需将句柄保存到RBX这类不会被覆盖的寄存器。 - 添加写入字节数指针:WriteFile的第四个参数需要传入指针接收实际写入字节数,不能直接传0,需在
.bss段分配变量存储该值。
修复后的代码
DEFAULT REL global main extern CreateFileA extern CloseHandle extern WriteFile section .data filename db "f.txt", 0 section .bss bytes_written resd 1 ; 存储实际写入字节数 section .text main: sub rsp, 48h ; 16字节对齐,预留参数空间 ; 调用CreateFileA创建/打开文件 mov rcx, filename ; 参数1: 文件名 mov rdx, 40000000h ; 参数2: GENERIC_WRITE mov r8, 2 ; 参数3: FILE_SHARE_WRITE xor r9, r9 ; 参数4: NULL 安全属性 mov dword [rsp+32], 2 ; 参数5: CREATE_ALWAYS mov dword [rsp+40], 80h ; 参数6: FILE_ATTRIBUTE_NORMAL call CreateFileA ; 检查句柄是否有效(INVALID_HANDLE_VALUE = -1) cmp rax, -1 je cleanup mov rbx, rax ; 保存文件句柄到RBX ; 调用WriteFile写入内容 mov rcx, rbx ; 参数1: 文件句柄 lea rdx, [filename] ; 参数2: 写入缓冲区(这里写入"f.txt") mov r8, 6 ; 参数3: 写入字节数(含终止0) mov r9, bytes_written ; 参数4: 实际写入字节数指针 mov qword [rsp+32], 0 ; 参数5: NULL 重叠结构 call WriteFile cleanup: ; 关闭文件句柄 mov rcx, rbx call CloseHandle xor eax, eax add rsp, 48h ret
内容的提问来源于stack exchange,提问作者dtroyan
相关产品推荐
相关产品推荐

