彙編 - 條件



組合語言中的條件執行是通過幾個迴圈和分支指令實現的。這些指令可以改變程式的控制流程。條件執行在兩種情況下出現:

序號 條件指令
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
廣告