You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:15:29