装配 - 条件


汇编语言中的条件执行是通过多个循环和分支指令来完成的。这些指令可以改变程序中的控制流程。在两种情况下观察到条件执行 -

先生。 有条件指示
1

无条件跳转

这是由 JMP 指令执行的。条件执行通常涉及将控制转移到不跟随当前正在执行的指令的指令的地址。控制权的转移可以是向前的,以执行一组新的指令,也可以是向后的,以重新执行相同的步骤。

2

条件跳转

这是由一组跳转指令 j<条件> 根据条件执行的。条件指令通过中断顺序流来转移控制,并通过更改 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 指令的语法是 -

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

条件跳转

如果条件跳转中满足某个指定条件,则控制流转移到目标指令。根据条件和数据,有许多条件跳转指令。

以下是用于算术运算的带符号数据的条件跳转指令 -

操作说明 描述 已测试的标志
乙脑/JZ 跳转等于或跳转零 采埃孚
JNE/JNZ 跳转不等于或跳转不为零 采埃孚
JG/JNLE 跳得更大或跳得不小于/等于 OF、SF、ZF
JGE/JNL 跳得更大/等于或跳得不少 的,SF
JL/JNGE 少跳或不大于/等于跳 的,SF
JLE/JNG 跳少/等于或跳不大于 OF、SF、ZF

以下是用于逻辑运算的无符号数据的条件跳转指令 -

操作说明 描述 已测试的标志
乙脑/JZ 跳转等于或跳转零 采埃孚
JNE/JNZ 跳转不等于或跳转不为零 采埃孚
日本航空/JNBE 跳到上面或跳到下面/等于 CF、采埃孚
日本航空/JNB 跳到上面/等于或跳到下面 CF
新山/JNAE 跳到下方或跳到不高于/等于 CF
JBE/JNA 跳到下面/等于或跳到上面 AF、CF

以下条件跳转指令具有特殊用途并检查标志的值 -

操作说明 描述 已测试的标志
江西成泽 如果 CX 为零则跳转 没有任何
杰成 如果进位则跳转 CF
江南公司 如果没有进位则跳转 CF
溢出则跳转
国家海洋局 如果没有溢出则跳转
日本/日本PE 跳转奇偶校验或跳转奇偶校验 PF
日本国家警察/日本特许厅 跳转无奇偶校验或跳转奇偶校验 PF
JS 跳跃符号(负值) 顺丰
JNS 跳转无符号(正值) 顺丰

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