MASM自定义结构体数组的文件存储实现问题咨询
MASM结构体数组定义与文件写入修正方案
先给你修正后的可运行代码,再拆解关键问题点:
.386 .model flat, stdcall option casemap :none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib ; 结构体定义要放在所有数据段、代码段之前,STRUCT是类型定义伪指令,不属于数据范畴 MyStruct STRUCT string db 4 dup(0) ; 刚好容纳"John"这类4字符名字,无需额外终止符 dw1 DWORD ? dw2 DWORD ? dw3 DWORD ? MyStruct ENDS .data? handle HANDLE ? ; 之前未声明文件句柄变量 written DWORD ? ; WriteFile需要的写入字节数输出变量 ; 标准结构体数组定义:指定类型+重复次数,sizeof可直接计算总大小,比resb更直观 MyArray MyStruct 10 dup(?) .data fileName db "myfile.dat",0 ; 字符串必须以0结尾,CreateFile要求C风格字符串 properNouns db "John",0,"Mike",0,"Emily",0,"Mary",0,"David",0 ; 每个名词单独加0,方便逐个读取 .code start: ; 填充结构体数组示例:把properNouns里的名字写入前5个结构体的string字段 mov esi, OFFSET properNouns mov edi, OFFSET MyArray mov ecx, 5 ; 对应properNouns里的5个名字 fill_loop: mov al, [esi] mov [edi.MyStruct.string], al ; 用MASM结构体成员访问语法赋值 inc esi inc edi cmp al, 0 jne fill_loop ; 跳过终止符,跳转到下一个结构体的起始位置 inc esi add edi, sizeof MyStruct - 4 ; 已写入4字节string,直接跳过剩余的dw1/dw2/dw3字段 loop fill_loop ; 打开文件 invoke CreateFile, ADDR fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL mov handle, eax cmp handle, INVALID_HANDLE_VALUE je cleanup ; 打开失败直接进入清理流程 ; 写入数组到文件:sizeof MyArray自动计算10个结构体的总字节数 invoke WriteFile, handle, ADDR MyArray, sizeof MyArray, ADDR written, NULL cleanup: ; 关闭文件(需判断句柄是否有效) cmp handle, INVALID_HANDLE_VALUE jne CloseHandle, handle invoke ExitProcess, 0 end start
关键问题修正说明
- 结构体定义位置:STRUCT是类型定义伪指令,不能放在
.data?或.data段内,必须放在所有段的最前面,让汇编器提前识别这个自定义类型。 - 数组定义方式:
MyArray MyStruct 10 dup(?)是MASM定义结构体数组的标准写法,汇编器会自动处理每个结构体的内存偏移,sizeof MyArray能直接返回数组总字节数;用resb虽然可行,但需要手动计算大小,且无法直接使用结构体成员访问语法,实用性远不如标准写法。 - 未声明变量:
handle(文件句柄)和written(写入字节数统计)是调用Windows API必须的变量,必须在.data?段中声明。 - 字符串终止符:
fileName和properNouns都要以0结尾,CreateFile要求传入C风格字符串,填充数组时也需要通过0来判断每个名字的结束位置。 - 数组填充逻辑:直接写入未初始化的数组会导致文件中出现垃圾数据,新增的填充循环演示了如何访问结构体成员,并将指定字符串写入数组。
- 错误处理:新增文件打开失败的判断,避免后续调用无效句柄导致程序崩溃。
内容的提问来源于stack exchange,提问作者Chad Botting
相关产品推荐
相关产品推荐

