高级语言常见的if语句如下:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式m)
语句m;
else
语句n;
MASM的IF伪指令
MASM也有类似写法的伪指令,但汇编器会在后台生成CMP和条件跳转指令。使用与C++和JAVA相同的运算符 ( 比如:<、>、== 和 !=)。表达式在运行时计算。下面的例子给出了一些有效的条件,使用的是 32 位寄存器和变量:
eax > 10000h
val1 <= 100
val2 == eax
val3 != ebx
(eax > 0) && (eax > 10000h)
(val1 <= 100) || (val2 <= 100)
(val2 != ebx) && !CARRY?
运算符 | 说明 |
expr1 == expr2 | 若 expr1 等于 expr2,则返回“真” |
expr1 != expr2 | 若 expr1 不等于 expr2,则返回“真” |
expr1 > expr2 | 若 expr1 大于 expr2,则返回"真” |
expr1 ≥ expr2 | 若 expr1 大于等于 expr2,则返回“真” |
expr1 < expr2 | 若 expr1 小于 expr2,则返回“真” |
expr1 ≤ expr2 | 若 expr1 小于等于 expr2,则返回“真” |
!expr1 | 若 expr 为假,则返回“真” |
expr1 expr2 | 对 expr1 和 expr2 执行逻辑 AND 运算 |
expr1 || expr2 | 对 1xprl 和 expr2 执行逻辑 OR 运算 |
expr1 & expr2 | 对 expr1 和 expr2 执行按位 AND 运算 |
CARR1? | 若进位标志位置 11则返回“真” |
OVERFLOW ? | 若溢出标志位置 1,则返回“真” |
PARITY ? | 若奇偶标志位置 1,则返回“真” |
SIGN ? | 若符号标志位置 1,则返回“真” |
ZERO ? | 若零标志位置 1,则返回“真” |
在使用 MASM 条件伪指令之前,一定要彻底了解怎样用纯汇编语言的指令实现条件分支。此外,在包含条件伪指令的程序汇编中,要查看列表文件以确认 MASM 生成的代码确实是编程者所需要的。
有符号数和无符号数的比较
关于有符号数和无符号数的比较的问题,汇编器根据定义数据的伪指令属于无符号或者有符号,来确定当遇到if伪指令时要用有符号还是无符号的跳转指令。
定义内存数据时需要伪指令如:sdword、dword,当遇到用寄存器与内存数据比较时,可以借此确定用有符号或者无符号跳转指令。但是当遇到寄存器与寄存器的比较,汇编器就无法确定寄存器中的数值是有符号的还是无符号。
复合表达式
很多复合布尔表达式使用逻辑 OR 和 AND 运算符。用 .IF 伪指令时,符号 || 表示的是逻辑 OR 运算符。符号 && 表示的是逻辑 AND 运算符。
.IF expression1 || expression2
statements
.ENDIF
.IF expression1 && expression2
statements
.ENDIF
SetCursorPosition 示例
下例给出的 SetCursorPosition 过程,根据两个输入参数 DH 和 DL,执行范围检查。Y 坐标(DH)范围必须为 0〜24。X 坐标(DL)范围必须为 0〜79。不论发现哪个坐标超出范围,都显示一条错误消息:
SetCursorPosition PROC
; 设置光标位置
; 接收: DL = X坐标, DH = Y坐标
; 检查 DL 和 DH 的范围
; 返回:无
;------------------------------------------------
.data
BadXCoordMsg BYTE "X-Coordinate out of range!",0Dh,0Ah,0
BadYCoordMsg BYTE "Y-Coordinate out of range!",0Dh,0Ah,0
.code
.IF (DL < 0) || (DL > 79)
mov edx,OFFSET BadXCoordMsg
call WriteString
jmp quit
.ENDIF
.IF (DH < 0) || (DH > 24)
mov edx,OFFSET BadYCoordMsg
call WriteString
jmp quit
.ENDIF
call Gotoxy
quit:
ret
SetCursorPosition ENDP
MASM 对 SetCursorPosition 进行预处理时,生成代码如下:
.code
;.IF (dl < 0) || (dl > 79)
cmp dl, OOOh
jb @C0002
cmp dl, 04Fh
jbe @C0001
@C0002:
mov edx,OFFSET BadXCoordMsg
call WriteString
jmp quit
;.ENDIF
@C0001:
;.IF (dh < 0) || (dh > 24)
cmp dh, OOOh
jb @COOO5
cmp dh, 018h
jbe @C0004
@COOO5:
mov edx,OFFSET BadYCoordMsg
call WriteString
jmp quit
;.ENDIF
@C0004:
call Gotoxy
quit:
ret
大学注册示例
假设有一个大学生想要进行课程注册。现在用两个条件来决定该生是否能注册:第一个条件是学生的平均成绩,范围为 0〜400,其中 400 是可能的最高成绩;第二个条件是学生期望获得的学分。可以使用多分支结构,包括 .IF、.ELSEIF 和 .ENDIF。示例如下。
.data
TRUE = 1
FALSE = 0
gradeAverage WORD 275 ; 要检查的数值
credits WORD 12 ; 要检查的数值
OkToRegister BYTE ?
.code
main PROC
mov OkToRegister,FALSE
.IF gradeAverage > 350
mov OkToRegister,TRUE
.ELSEIF (gradeAverage > 250) && (credits <= 16)
mov OkToRegister,TRUE
.ELSEIF (credits <= 12)
mov OkToRegister,TRUE
.ENDIF
对应的汇编代码如下:
.386
.model flat, stdcall
.stack 4096
ExitProcess proto, dwExitcode:dword
include irvine32.inc
.data
true = 1
false = 0
gradeAverage word 215 ; 要检查的数值
credits word 12 ; 要检查的数值
OkToRegister byte ?
.code
main proc
nop
mov byte ptr OkToRegister, false ;false是一个立即数,默认为32位,此处用byte ptr。
cmp gradeaverage, 350
jbe @001
jmp finish
@001:
cmp gradeaverage, 250
jbe @002
cmp credits, 16
jbe finish
@002:
cmp credits, 12
ja quit
finish:
mov byte ptr OkToRegister, true
quit: ret
main endp
end main