어셈블리어에서 조건부 실행은 여러개의 반복문과 분기 명령으로 구현한다. 이 명령어는 프로그램의 조작 흐름을 변경할 수 있다. 조건부 실행은 두 가지의 시나리오가 있다.
조건 명령 | |
---|---|
1 | 무조건 점프(Unconditional jump) JMP 명령어로 실행된다. |
2 | 조건부 점프(Conditional jump) 조건에 따른 점프 명령 j<조건>으로 실행된다. |
조건 명령어에 대해 이야기하기 전에 CMP 명령어에 대해 먼저 이야기하자.
CMP 명령어는 두 개의 피연산자를 비교한다. 일반적으로 조건부 실행에 사용된다. 기본적으로 CMP 명령어는 피연산자들을 비교하기 위해 한 피연산자에서 나머지 다른 피연산자를 뺀다. 이 동작은 목적지(destination) 피연산자나 원본(source) 피연산자에 영향을 주지 않는다. 의사 결정을 위한 조건부 점프 명령어와 같이 사용된다.
구문
CMP destination, source
CMP 명령어는 두 개의 숫자 데이터 필드를 비교한다. 목적지(destination) 피연산자는 레지스터나 메모리에 위치할 수 있다. 원본(source) 피연산자는 상수 데이터이거나 레지스터, 메모리에 위치할 수 있다.
예제
CMP DX, 00 ; DX 값과 0을 비교한다.
JE L7 ; 같다면, 레이블 L7로 점프한다.
.
.
L7 : ...
CMP 명령어는 카운터 값이 반복문의 실행 반복 횟수에 다다랐는지 비교하기 위해 자주 사용된다.
INC EDX
CMP EDX, 10 ; 카운터가 10이 됐는지 비교한다.
JLE LP1 ; 만약 작거나 같을 경우, LP1으로 점프한다.
앞서서 언급한 것처럼, 무조건 점프는 JMP 명령어로 실행된다. 조건부 실행은 주로 코드의 순차적인 실행 흐름을 따르지 않는 제어 전환 동작을 한다. 제어 전환은 새로운 명령어 세트를 실행하기 위해 현재 실행 명령어의 앞으로 갈 수도, 같은 단계를 다시 실행하기 위해 현재 실행 명령어의 뒤로 갈 수도 있다.
구문
JMP 명령어는 제어 흐름 즉시 전환되는 레이블의 이름을 제공한다. JMP 명령어의 구문은 다음과 같다.
JMP label
예제
JMP 명령어를 설명하는 코드는 다음과 같다.
MOV AX, 00 ; AX를 0으로 초기화
MOV BX, 00 ; BX를 0으로 초기화
MOV CX, 01 ; CX를 0으로 초기화
L20:
ADD AX, 01 ; AX 증가
ADD BX, AX ; AX에 BX를 더한다.
SHL CX, 1 ; CX를 왼쪽으로 시프트하면 CX의 값이 두배가 된다.
JMP L20 ; L20을 반복
조건부 점프에서 특정 조건을 만족한다면, 제어 흐름이 타겟 명령어로 전환된다. 조건과 데이터에 따라 매우 많은 조건부 점프 명령어가 존재한다.
다음은 산술 연산에 사용되는 부호가 있는 데이터를 사용하는 조건부 점프 명령어이다.
명령어 | 설명 | 테스트 플래그 |
---|---|---|
JE/JZ | 같으면 점프/0이면 점프 | ZF |
JNE/JNZ | 같지 않으면 점프/0이 아니면 점프 | ZF |
JG/JNLE | 크면 점프/작지 않거나 같지 않으면 점프 | OF, SF, ZF |
JGE/JNL | 크거나 같으면 점프/작지 않으면 점프 | OF, SF |
JL/JNGE | 작으면 점프/크지 않거나 같지 않으면 점프 | OF, SF |
JLE/JNG | 작거나 같으면 점프/크지 않으면 점프 | OF, SF, ZF |
다음은 논리 연산에 사용되는 부호가 없는 데이터를 사용하는 조건부 점프 명령어이다.
명령어 | 설명 | 테스트 플래그 |
---|---|---|
JE/JZ | 같으면 점프/0이면 점프 | ZF |
JNE/JNZ | 같지 않으면 점프/0이 아니면 점프 | ZF |
JA/JNBE | 크면 점프/작지 않거나 같지 않으면 점프 | CF, ZF |
JAE/JNB | 크거나 같으면 점프/작지 않으면 점프 | CF |
JB/JNAE | 작으면 점프/크지 않거나 같지 않으면 점프 | CF |
JBE/JNA | 작거나 같으면 점프/크지 않으면 점프 | AF, CF |
다음은 플래그의 값을 확인하고 특별한 용도를 가진 조건부 점프 명령이다.
명령어 | 설명 | 테스트 플래그 |
---|---|---|
JXCZ | CX가 0이면 점프 | none |
JC | CF가 1이면 점프 | CF |
JNC | CF가 0이면 점프 | CF |
JO | OF가 1이면 점프 | OF |
JNO | OF가 0이면 점프 | OF |
JP/JPE | PF가 1이면 점프/짝수일 때 점프 | PF |
JNP/JPO | PF가 0이면 점프/홀수일 때 점프 | PF |
JS | SF가 1이면 점프(음수) | SF |
JNS | SF가 0이면 점프(양수) | SF |
J<조건> 명령어의 구문은 다음과 같다.
예제
CMP AL, BL
JE EQUAL
CMP AL, BH
JE EQUAL
CMP AL, CL
JE EQUAL
NON_EQUAL: ...
EQUAL: ...
다음은 세 개의 변수 중 가장 큰 변수를 출력하는 프로그램이다. 변수는 두자리 변수이다. 세 변수는 num1, num2, num3이고 각각 47, 22, 31이다.
❗️ 64비트 Intel macOS에서 동작하는 코드이다.
section .text
global _main
_main:
mov r10, num1
mov ecx, [r10]
mov r10, num2
cmp ecx, [r10]
jg check_third_num
mov ecx, [r10]
check_third_num:
mov r10, num3
cmp ecx, [r10]
jg _exit
mov ecx, [r10]
_exit:
mov r10, largest
mov [r10], ecx
mov rsi, msg
mov rdx, len
mov rdi, 1
mov rax, 0x2000004
syscall
mov rsi, largest
mov rdx, 2
mov rdi, 1
mov rax, 0x2000004
syscall
mov rax, 0x2000001
mov rdi, 0
syscall
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:
47s