在 MASM 高級宏指令 .if、.while、.repeat 等中進行有符號數比較時,若直接寫 .if eax < 0,編譯器可能將其視為無符號比較,生成 JB (Jump if Below, 無符號小於) 而非 JL (Jump if Less, 有符號小於),導致負數被誤判為大正數,邏輯錯誤。
.if p.y < 0
; 代碼段 1
.elseif p.y > eax
; 代碼段 2
.endif
若 p.y = -100 (0xFFFFFF9C),編譯器生成 CMP p.y, 0 / JB xxx。無符號下 0xFFFFFF9C (4294967196) 不小於 0,JB 不跳轉,代碼段 1 永不執行。
MASM 宏指令無法自動推斷操作數是否為有符號類型。默認按無符號處理,生成 JA/JB/JAE/JBE 系列指令。有符號比較需用 JG/JL/JGE/JLE。
.if SDWORD PTR p.y < 0
; 正確生成 CMP ... / JL ...
.endif
SDWORD PTR 告訴編譯器將操作數視為 32 位有符號整數。同理:SWORD PTR (16位)、SBYTE PTR (8位)。
.if p.y <= -1 ; 等價於 p.y < 0
; 編譯器識別 -1 為有符號常數,自動選擇 JLE/JL
.endif
cmp eax, 0
jle @F
; p.y <= 0 邏輯
@@:
cmp p.y, eax
jle @F
; p.y <= eax 邏輯
@@:
.while、.repeat/.until、.break/.continue 條件判斷同樣存在此問題。< > <= >= 的宏條件判斷均需注意。SDWORD PTR var、SWORD PTR var。<= -1 觸發有符號邏輯。/Fl 生成列表文件或反彙編確認實際跳轉指令 (JL vs JB)。SIGNED_CMP MACRO reg, val 內部強制類型,統一風格。這不是 MASM 的 Bug,而是宏指令設計上缺乏類型推導能力。開發者必須通過顯式類型轉換 (SDWORD PTR) 或常數技巧引導編譯器生成正確的有符號跳轉指令。養成「比較即註明符號性」的習慣,能避免極難排查的邏輯錯誤。