如何在MASM汇编中比较数值与STRUCT字段的值?
问题解决:筛选价格低于输入值的商品结构体
问题描述
需要输出价格低于输入值的Good结构体实例,但当前代码要么输出全部结构体,要么什么都不输出。已初始化3个Good对象,从键盘输入数值并转换后,比较结构体的Price字段时无法得到正确结果。原代码如下:
.686 .model flat, stdcall option casemap:none include C:\masm32\include\windows.inc include C:\masm32\include\user32.inc include C:\masm32\include\kernel32.inc include C:\masm32\include\masm32.inc includelib C:\masm32\lib\user32.lib includelib C:\masm32\lib\kernel32.lib includeLib C:\masm32\lib\masm32.lib Good STRUCT Abbr BYTE 20 DUP(?) Descr BYTE 20 DUP(?) Price DWORD ? Count DWORD ? Good ENDS PrintGoods PROTO ptrGood:PTR Good .data sConsTitle BYTE "Lab rab 5", 0 strTask BYTE "Output list of goods that lower then entered price", 0Dh, 0Ah, 0Ah, 0h sPrompt BYTE "Enter price", 0Dh, 0Ah, 0h clrt BYTE 0Ah, 0Dh, 0 comma BYTE ", ", 0 buffer BYTE 20 DUP(0) good_1 Good <"q", "g", 1600, 13> good_2 Good <"w", "m", 800, 24> good_3 Good <"e", "s", 250, 24> .data? hStdin DWORD ? priceToComp DWORD ? .code main PROC invoke SetConsoleTitle, addr sConsTitle invoke StdOut, addr strTask invoke StdOut, offset sPrompt invoke StdIn, offset buffer, lengthof buffer invoke atol, addr buffer mov DWORD PTR priceToComp, eax invoke PrintGoods, addr good_1 invoke PrintGoods, addr good_2 invoke PrintGoods, addr good_3 invoke Sleep, INFINITE invoke ExitProcess, NULL main ENDP PrintGoods PROC ptrGood:PTR Good mov eax, priceToComp cmp eax, Good.Price jg m1 jmp exit m1: mov ebx, ptrGood invoke StdOut, ebx invoke StdOut, addr comma add ebx, SIZEOF Good.Abbr invoke StdOut, ebx invoke StdOut, addr comma add ebx, sizeof Good.Descr invoke ltoa, [ebx], addr buffer invoke StdOut, addr buffer invoke StdOut, addr comma add ebx, sizeof Good.Price invoke ltoa, [ebx], addr buffer invoke StdOut, addr buffer invoke StdOut, addr clrt exit: ret PrintGoods ENDP END main
错误原因分析
- 结构体字段访问错误:
cmp eax, Good.Price中的Good.Price只是结构体中Price字段的固定偏移量(40字节,因Abbr和Descr各占20字节),并非当前传入的结构体实例的实际Price值,导致比较逻辑完全错误。 - 字符串初始化不规范:初始化
Good对象时,"q"这类字符串未补0,StdOut输出时会读取到后续垃圾数据,引发乱码。 - 字段偏移计算冗余:手动累加偏移量访问字段易出错,可直接用结构体类型+字段名的方式简化访问。
修正后的代码
.686 .model flat, stdcall option casemap:none include C:\masm32\include\windows.inc include C:\masm32\include\user32.inc include C:\masm32\include\kernel32.inc include C:\masm32\include\masm32.inc includelib C:\masm32\lib\user32.lib includelib C:\masm32\lib\kernel32.lib includeLib C:\masm32\lib\masm32.lib Good STRUCT Abbr BYTE 20 DUP(?) Descr BYTE 20 DUP(?) Price DWORD ? Count DWORD ? Good ENDS PrintGoods PROTO ptrGood:PTR Good .data sConsTitle BYTE "Lab rab 5", 0 strTask BYTE "输出价格低于输入值的商品列表", 0Dh, 0Ah, 0Ah, 0h sPrompt BYTE "请输入价格:", 0Dh, 0Ah, 0h clrt BYTE 0Ah, 0Dh, 0 comma BYTE ", ", 0 buffer BYTE 20 DUP(0) ; 规范初始化字符串,补0避免乱码 good_1 Good <"q", 0, 18 DUP(?), "g", 0, 18 DUP(?), 1600, 13> good_2 Good <"w", 0, 18 DUP(?), "m", 0, 18 DUP(?), 800, 24> good_3 Good <"e", 0, 18 DUP(?), "s", 0, 18 DUP(?), 250, 24> .data? priceToComp DWORD ? .code main PROC invoke SetConsoleTitle, addr sConsTitle invoke StdOut, addr strTask invoke StdOut, offset sPrompt invoke StdIn, offset buffer, lengthof buffer invoke atol, addr buffer mov priceToComp, eax invoke PrintGoods, addr good_1 invoke PrintGoods, addr good_2 invoke PrintGoods, addr good_3 invoke Sleep, INFINITE invoke ExitProcess, NULL main ENDP PrintGoods PROC ptrGood:PTR Good mov ebx, ptrGood ; 获取当前商品的Price值,与输入价格比较 mov eax, priceToComp cmp [ebx].Good.Price, eax jge exit ; 商品价格≥输入价格则跳过输出 ; 输出Abbr invoke StdOut, [ebx].Good.Abbr invoke StdOut, addr comma ; 输出Descr invoke StdOut, [ebx].Good.Descr invoke StdOut, addr comma ; 输出Price invoke ltoa, [ebx].Good.Price, addr buffer invoke StdOut, addr buffer invoke StdOut, addr comma ; 输出Count invoke ltoa, [ebx].Good.Count, addr buffer invoke StdOut, addr buffer invoke StdOut, addr clrt exit: ret PrintGoods ENDP END main
关键修正点
- 正确访问结构体实例字段:使用
[ebx].Good.Price获取当前传入实例的Price值,而非固定偏移量。 - 调整比较逻辑:
cmp [ebx].Good.Price, eax后用jge exit,确保仅输出价格低于输入值的商品。 - 规范字符串初始化:每个字符串后补0并填充剩余字节,避免
StdOut输出乱码。 - 简化字段访问:直接用结构体类型+字段名的方式访问,代码更易读维护。
内容的提问来源于stack exchange,提问作者woolMe
相关产品推荐
相关产品推荐

