[libasm] Assembly - 조건문

Park Sejin·2021년 4월 10일
0

[libasm] nasm 어셈블러

목록 보기
10/12
post-thumbnail

어셈블리어에서 조건부 실행은 여러개의 반복문과 분기 명령으로 구현한다. 이 명령어는 프로그램의 조작 흐름을 변경할 수 있다. 조건부 실행은 두 가지의 시나리오가 있다.

조건 명령
1무조건 점프(Unconditional jump)
JMP 명령어로 실행된다.
2조건부 점프(Conditional jump)
조건에 따른 점프 명령 j<조건>으로 실행된다.

조건 명령어에 대해 이야기하기 전에 CMP 명령어에 대해 먼저 이야기하자.

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

다음은 플래그의 값을 확인하고 특별한 용도를 가진 조건부 점프 명령이다.

명령어설명테스트 플래그
JXCZCX가 0이면 점프none
JCCF가 1이면 점프CF
JNCCF가 0이면 점프CF
JOOF가 1이면 점프OF
JNOOF가 0이면 점프OF
JP/JPEPF가 1이면 점프/짝수일 때 점프PF
JNP/JPOPF가 0이면 점프/홀수일 때 점프PF
JSSF가 1이면 점프(음수)SF
JNSSF가 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

출처

tutorialspoint.com

0개의 댓글