汇编语言条件跳转应用及示例
条件跳转指令常常用这些状态标志位来决定是否将控制转向代码标号。例如,假设有一个名为 status 的 8 位内存操作数,它包含了与计算机连接的一个外设的状态信息。如果该操作数的位 5 等于 1,表示外设离线,则下面的指令就跳转到标号:
mov al, status
test al, 00100000b ;测试位 5
jnz DeviceOffline
mov al, status
test al, 00010011b ;测试位 0、1、4
jnz InputDataByte
mov al, status
and al,10001100b ;屏蔽位 2、3 和 7
cmp al, 10001100b ;所有位都置 1 ?
je ResetMachine ;是:跳转
两个数中的较大数
下面的代码比较了 EAX 和 EBX 中的两个无符号整数,并且把其中较大的数送入 EDX:
mov edx, eax ;假设EAX存放较大的数
cmp eax, ebx ;若 EAX ≥ EBX
jae L1 ;跳转到 L1
mov edx, ebx ;否则,将 EBX 的值送入 EDX
L1: ;EDX 中存放的是较大的数
三个数中的最小数
下面的代码比较了分别存放于三个变量 VI、V2 和 V3 的无符号 16 位数值,并且把其中最小的数送入AX:
.data
V1 WORD ?
V2 WORD ?
V3 WORD ?
.code
mov ax, V1 ;假设 V1 是最小值
cmp ax, V2 ;如果 AX ≤ V2
jbe L1 ;跳转到 L1
mov ax, V2 ;否则,将 V2 送入 AX
LI: cmp ax, V3 ;如果 AX ≤ V3
jbe L2 ;跳转到L2
mov ax, V3 ;否则,将V3送入AX
L2 :
循环直到按下按键
下面的 32 位代码会持续循环,直到用户按下任意一个标准的字母数字键。如果输入缓冲区中当前没有按键,那么 Irvine32 库中的 ReadKey 函数就会将零标 志位置1:
.data
char BYTE ?
.code
L1: mov eax, 10
call Delay ;创建 10 毫秒的延迟;
call ReadKey ;检查按键
jz L1 ;如果没有按键则循环
mov char, AL ;保存字符)
【示例 1】:顺序搜索数组
常见的编程任务是在数组中搜索满足某些条件的数值。例如,下述程序就是在一个 16 位数组中寻找第一个非零数值。如果找到,则显示该数值;否则,就显示一条信息,以说明没有发现非零数值:;扫描数组 (ArrayScan.asm) ;扫描数组寻找第一个非零数值 INCLUDE Irvine32.inc .data intArray SWORD 0,0,0,0,1,20,35,-12,66,4,0 ;intArray SWORD 1,0,0,0 ;候补测试数据 ;intArray SWORD 0,0,0,0 ;候补测试数据 ;intArray SWORD 0,0,0,1 ;候补测试数据 noneMsg BYTE "A non-zero value was not found",0 .code main PROC mov ebx,OFFSET intArray ;指向数组 mov ecx,LENGTHOF intArray ;循环计数器 L1: cmp WORD PTR [ebx],0 ;将数值与0比较 jnz found ;寻找数值 add ebx,2 ;指向下一个元素 loop L1 ;继续循环 jmp notFound ;没有发现非零数值 found: movsx eax,WORD PTR[ebx] ;送人EAX并进行符号扩展 call WriteInt jmp quit notFound: mov edx,OFFSET noneMsg ;显示“没有发现”消息 call WriteString quit: call Crlf exit main ENDP END main本程序包含了可以替换的测试数据,它们已经被注释出来。取消这些注释行,就可 以用不同的数据配置来测试程序。
【示例 2】:简单字符串加密
XOR 指令有一个有趣的属性。如果一个整数 X 与 Y 进行 XOR,其结果再次与 Y 进行 XOR,则最后的结果就是 X:( ( X ㊉ Y ) ㊉ Y) = X
XOR 的可逆性为简单数据加密提供了一种方便的途径:明文消息转换成加密字符串,这个加密字符串被称为密文,加密方法是将该消息与被称为密钥的第三个字符串按位进行 XOR 操作。预期的查看者可以用密钥解密密文,从而生成原始的明文。下面将演示一个使用对称加密的简单程序,即用同一个密钥既实现加密又实现解密的过程。运行时,下述步骤依序发生:
1) 用户输入明文。
2) 程序使用单字符密钥对明文加密,产生密文并显示在屏幕上。
3) 程序解密密文,产生初始明文并显示出来。
程序清单完整的程序清单如下所示:
;加密程序 (Encrypt.asm) INCLUDE Irvine32.inc KEY = 239 ;1-255之间的任一值 BUFMAX = 128 ;缓冲区的最大容量 .data sPrompt BYTE "Enter the plain text:",0 sEncrypt BYTE "Cipher text",0 sDecrypt BYTE "Decrypted:",0 buffer BYTE BUFMAX+1 DUP(0) bufSize DWORD ? .code main PROC call InputTheString ;输入明文 call TranslateBuffer ;加密缓冲区 mov edx,OFFSET sEncrypt ;显示加密消息 call DisplayMessage call TranslateBuffer ;解密缓冲区 mov edx,OFFSET sDecrypt ;显示解密消息 call DisplayMessage exit main ENDP ;----------------------------------------- InputTheString PROC ; ;提示用户输入一个纯文本字符串 ;保存字符串和它的长度 ;接收:无 ;返回:无 ;----------------------------------------- pushad ;保存32位寄存器 mov edx,OFFSET sPrompt ;显示提示 call WriteString mov ecx,BUFMAX ;字符计数器最大值 mov edx,OFFSET buffer ;指向缓冲区 call ReadString ;输入字符串 mov bufSize,eax ;保存长度 call Crlf popad ret InputTheString ENDP ;----------------------------------------- DisplayMessage PROC ; ;显示加密或解密消息 ;接收:EDX指向消息 ;返回:无 ;----------------------------------------- pushad call WriteString mov edx,OFFSET buffer ;显示缓冲区 call WriteString call Crlf call Crlf popad ret DisplayMessage ENDP ;----------------------------------------- TranslateBuffer PROC ; ;字符串的每个字节都与密钥字节进行异或 ;实现转换 ;接收:无 ;返回:无 ;----------------------------------------- pushad mov ecx,bufSize ;循环计数器 mov esi,0 ;缓冲区索引初始值赋0 L1: xor buffer[esi],KEY ;转换一个字节 inc esi ;指向下一个字节 loop L1 popad ret TranslateBuffer ENDP END main