汇编 - 条件
汇编语言中的条件执行是通过几个循环和分支指令实现的。这些指令可以改变程序的控制流程。条件执行在两种情况下出现:
序号 | 条件指令 |
---|---|
1 | 无条件跳转 这是由JMP指令执行的。条件执行通常涉及将控制转移到当前正在执行的指令之后地址的指令。控制转移可以是向前的,以执行一组新的指令,也可以是向后的,以重新执行相同的步骤。 |
2 | 条件跳转 这是由一组跳转指令j<condition>根据条件执行的。条件指令通过打破顺序流程来转移控制,它们通过更改IP中的偏移值来做到这一点。 |
在讨论条件指令之前,让我们先讨论CMP指令。
CMP指令
CMP指令比较两个操作数。它通常用于条件执行。此指令基本上从另一个操作数中减去一个操作数,以比较操作数是否相等。它不会干扰目标操作数或源操作数。它与条件跳转指令一起用于决策。
语法
CMP destination, source
CMP比较两个数值数据字段。目标操作数可以位于寄存器或内存中。源操作数可以是常量(立即数)数据、寄存器或内存。
示例
CMP DX, 00 ; Compare the DX value with zero JE L7 ; If yes, then jump to label L7 . . L7: ...
CMP经常用于比较计数器值是否已达到循环需要运行的次数。考虑以下典型条件:
INC EDX CMP EDX, 10 ; Compares whether the counter has reached 10 JLE LP1 ; If it is less than or equal to 10, then jump to LP1
无条件跳转
如前所述,这是由JMP指令执行的。条件执行通常涉及将控制转移到当前正在执行的指令之后地址的指令。控制转移可以是向前的,以执行一组新的指令,也可以是向后的,以重新执行相同的步骤。
语法
JMP指令提供一个标签名称,控制流立即转移到该标签。
JMP label
示例
以下代码片段说明了JMP指令:
MOV AX, 00 ; Initializing AX to 0 MOV BX, 00 ; Initializing BX to 0 MOV CX, 01 ; Initializing CX to 1 L20: ADD AX, 01 ; Increment AX ADD BX, AX ; Add AX to BX SHL CX, 1 ; shift left CX, this in turn doubles the CX value JMP L20 ; repeats the statements
条件跳转
如果条件跳转中满足某些指定的条件,则控制流将转移到目标指令。根据条件和数据,有许多条件跳转指令。
以下是用于算术运算的有符号数据的条件跳转指令:
指令 | 描述 | 测试的标志 |
---|---|---|
JE/JZ | 相等跳转或零跳转 | ZF |
JNE/JNZ | 不相等跳转或非零跳转 | ZF |
JG/JNLE | 大于跳转或不小于/等于跳转 | OF, SF, ZF |
JGE/JNL | 大于/等于跳转或不小于跳转 | OF, SF |
JL/JNGE | 小于跳转或不大于/等于跳转 | OF, SF |
JLE/JNG | 小于/等于跳转或不大于跳转 | OF, SF, ZF |
以下是用于逻辑运算的无符号数据的条件跳转指令:
指令 | 描述 | 测试的标志 |
---|---|---|
JE/JZ | 相等跳转或零跳转 | ZF |
JNE/JNZ | 不相等跳转或非零跳转 | ZF |
JA/JNBE | 高于跳转或不低于/等于跳转 | CF, ZF |
JAE/JNB | 高于/等于跳转或不低于跳转 | CF |
JB/JNAE | 低于跳转或不高于/等于跳转 | CF |
JBE/JNA | 低于/等于跳转或不高于跳转 | AF, CF |
以下条件跳转指令具有特殊用途并检查标志的值:
指令 | 描述 | 测试的标志 |
---|---|---|
JXCZ | 如果CX为零则跳转 | 无 |
JC | 进位跳转 | CF |
JNC | 无进位跳转 | CF |
JO | 溢出跳转 | OF |
JNO | 无溢出跳转 | OF |
JP/JPE | 奇偶校验跳转或偶校验跳转 | PF |
JNP/JPO | 无奇偶校验跳转或奇校验跳转 | PF |
JS | 符号跳转(负值) | SF |
JNS | 无符号跳转(正值) | SF |
J<condition>指令集的语法:
示例:
CMP AL, BL JE EQUAL CMP AL, BH JE EQUAL CMP AL, CL JE EQUAL NON_EQUAL: ... EQUAL: ...
示例
以下程序显示三个变量中最大的一个。这些变量是两位数变量。三个变量num1、num2和num3的值分别为47、22和31:
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point mov ecx, [num1] cmp ecx, [num2] jg check_third_num mov ecx, [num2] check_third_num: cmp ecx, [num3] jg _exit mov ecx, [num3] _exit: mov [largest], ecx mov ecx,msg mov edx, len mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov ecx,largest mov edx, 2 mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov eax, 1 int 80h section .data msg db "The largest digit is: ", 0xA,0xD len equ $- msg num1 dd '47' num2 dd '22' num3 dd '31' segment .bss largest resb 2
编译并执行上述代码后,将产生以下结果:
The largest digit is: 47