汇编 - 条件



汇编语言中的条件执行是通过几个循环和分支指令实现的。这些指令可以改变程序的控制流程。条件执行在两种情况下出现:

序号 条件指令
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
广告