使用汇编语言实现IF语句
IF 结构包含一个布尔表达式,其后有两个语句列表:一个是当表达式为真时执行,另一个是当表达式为假时执行:
【示例 1】下面的 C++ 代码中,如果 op1 等于 op2,则执行两条赋值语句:
下面实现 IF 语句的程序是高效的,当逻辑表达式为真时,它允许代码“通过”直达两条期望被执行的 MOV 指令:
【示例 2】NTFS 文件存储系统中,磁盘簇的大小取决于磁盘卷的总容量。如下面的伪代码所示,如果卷大小(用变量 terrabytes 存放)不超过 16TB,则簇大小设置为 4096。否则, 簇大小设置为 8192:
白盒测试需要源代码,并对输入变量进行不同的赋值。对每个输入组合,要手动跟踪源代码,验证其执行路径和子程序产生的输出。下面,通过嵌套 IF 语句的汇编程序来看看这个测试过程:
if( boolean-expression )
statement-list-1
else
statement-list-2
【示例 1】下面的 C++ 代码中,如果 op1 等于 op2,则执行两条赋值语句:
if( op1 = op2 ) { X = 1; Y = 2; }在汇编语言中,这种 IF 语句转换为条件跳转和 CMP 指令。由于 op1 和 op2 都是内存操作数(变量),因此,在执行 CMP 之前,要将其中的一个操作数送入寄存器。
下面实现 IF 语句的程序是高效的,当逻辑表达式为真时,它允许代码“通过”直达两条期望被执行的 MOV 指令:
mov eax, op1 cmp eax,op2 ; op1 == op2? jne L1 ; 否:跳过后续指令 mov X, 1 ; 是:X, Y 赋值 mov Y, 2 L1:如果用 JE 来实现 == 运算符,生成的代码就没有那么紧凑了(6 条指令,而非 5 条指令):
mov eax, op1 cmp eax,op2 ; op1 == op2? je L1 ; 是:跳转到 L1 jmp L2 ; 否:跳过赋值语句 LI: mov X, 1 ; X, Y 赋值 mov Y, 2 L2 :从上面的例子可以看出,相同的条件结构在汇编语言中有多种实现方法。上面给出 的编译代码示例只代表一种假想的编译器可能产生的结果。
【示例 2】NTFS 文件存储系统中,磁盘簇的大小取决于磁盘卷的总容量。如下面的伪代码所示,如果卷大小(用变量 terrabytes 存放)不超过 16TB,则簇大小设置为 4096。否则, 簇大小设置为 8192:
clusterSize = 8192;
if terrabytes < 16
clusterSize = 4096;
mov clusterSize, 8192 ;假设较大的磁盘簇 cmp terrabytes, 16 ;小于 16TB? jae next mov clusterSize, 4096 ;切换到较小的磁盘簇 next:【示例 3】下面的伪代码有两个分支:
if op1 > op2
call Routine1
else
call Routine2
end if
mov eax, op1 ; opl送入寄存器 cmp eax, op2 ; opl > op2? jg A1 ; 是:调用 Routine1 call Routine2 ; 否:调用 Routine2 jmp A2 ;退出工F语句 A1: call Routine1 A2:
白盒测试
复杂条件语句可能有多个执行路径,这使得它们难以进行调试检查(查看代码)。程序员经常使用的技术称为白盒测试,用来验证子程序的输入和相应的输出。白盒测试需要源代码,并对输入变量进行不同的赋值。对每个输入组合,要手动跟踪源代码,验证其执行路径和子程序产生的输出。下面,通过嵌套 IF 语句的汇编程序来看看这个测试过程:
if op1 == op2 if X > Y call Routine1 else call Routine2 end if else call Routine3 end if下面是可能的汇编语言翻译,加上了参考行号。程序改变了初始条件(op1 == op2),并立即跳转到 ELSE 部分。剩下要翻译的内容是内层 IF-ELSE 语句:
mov eax, op1 cmp eax, op2 ;op1 == op2? jne L2 ;否:调用 Routine3 ; 处理内层 IF-ELSE 语句。 mov eax, X cmp eax, Y ; X > Y? jg L1 ; 是:调用 Routine1 call Routine2 ; 否:调用 Routine2 jmp L3 ; 退出 L1: call Routine1 ; 调用 Routine1 jmp L3 ; 退出 L2: call Routine3 L3:下表给出了示例代码的白盒测试结果。前四列对 op1、op2、X 和 Y 进行测试赋值。第 5 列和第 6 列对生成的执行路径进行了验证。
op1 | op2 | X | Y | 执行行序列 | 调用 |
---|---|---|---|---|---|
10 | 20 | 30 | 40 | 1, 2, 3, 11, 12 | Rountine3 |
10 | 20 | 40 | 30 | 1, 2, 3, 11, 12 | Rountine3 |
10 | 10 | 30 | 40 | 1, 2, 3, 4, 5, 6, 7, 8, 12 | Rountine2 |
10 | 10 | 40 | 30 | 1, 2, 3, 4, 5, 6, 9, 10, 12 | Rountine1 |