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

如何在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

错误原因分析

  1. 结构体字段访问错误:cmp eax, Good.Price中的Good.Price只是结构体中Price字段的固定偏移量(40字节,因Abbr和Descr各占20字节),并非当前传入的结构体实例的实际Price值,导致比较逻辑完全错误。
  2. 字符串初始化不规范:初始化Good对象时,"q"这类字符串未补0,StdOut输出时会读取到后续垃圾数据,引发乱码。
  3. 字段偏移计算冗余:手动累加偏移量访问字段易出错,可直接用结构体类型+字段名的方式简化访问。

修正后的代码

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 21:32:01