[libasm] Assembly - 논리 연산

Park Sejin·2021년 4월 7일
0
post-thumbnail

프로세서 명령어 세트는 AND, OR, XOR, TEST, NOT 명령어를 제공한다. 이 명령어들은 프로그램의 필요에 따라 비트를 test, set, clear한다.

명령어들은 다음과 같다.

명령어형식
1ANDAND 피연산자1, 피연산자2
2OROR 피연산자1, 피연산자2
3XORXOR 피연산자1, 피연산자2
4TESTTEST 피연산자1, 피연산자2
5NOTNOT 피연산자1

모든 경우의 첫 번째 피연산자는 레지스터나 메모리에 위치한다. 두 번째 피연산자는 레지스터나 메모리에 위치하거나 즉시 상수 값(immediate constant value)이다. 하지만, 메모리-메모리 간의 연산은 불가능하다. 이 명령어들은 피연산자의 비트를 비교하거나 일치시킨다. 그리고 CF, OF, PF, SF, ZF 플래그를 설정한다.

AND 명령어

AND 명령어는 비트 단위(bitwise) AND 명령을 하기 위해 사용된다. 비트 단위 AND 명령어는 같은 자리의 비트가 둘 다 1이라면 1을 반환하고, 그렇지 않으면 0을 반환한다. 예를 들어,

             Operand1:    0101
             Operand2:    0011
------------------------------
After AND -> Operand1:    0001

AND 명령어는 하나 또는 그 이상의 비트를 클리어하는데 사용할 수 있다. 예를 들어, BL 레지스터가 0011 1010을 담고 있고, 상위 비트들을 0으로 초기화하고 하고자 한다면, 0FH와 AND 연산을 하면 된다.

AND BL, 0FH   ; BL을 0000 1010로 변경한다.

다른 예를 들어보자. 주어진 숫자가 짝수인지 홀수인지 확인하고 싶다면, 숫자의 최하위 비트(least significant bit)를 확인하면 된다. 최하위 비트가 1이라면, 숫자는 홀수이고 0이라면, 짝수이다.

숫자가 AL레지스터에 저장되어 있다고 하면, 다음과 같이 할 수 있다.

AND  AL, 01H       ; AL과 0000 0001의 AND 연산
JZ   EVEN_NUMBER

이에 관한 프로그램은 다음과 같다.

❗️ 64비트 Intel macOS에서 동작하는 코드이다.

section .text
	global _main

_main:
	mov		ax, 8h			; ax에 8저장
	and		ax, 1			; ax과 1 AND 연산
						; AND 연산결과가 0이면 zero flag가 1
						; AND 연산결과가 1이면 zero flag가 0
	jz		even			; zero flag가 1인 경우, even로 이동
	mov		rax, 0x2000004
	mov		rdi, 1
	mov		rsi, odd_msg
	mov		rdx, len2
	syscall
	jmp		outprog

even:
	mov		ah, 09h
	mov		rax, 0x2000004
	mov		rdi, 1
	mov		rsi, even_msg
	mov		rdx, len1
	syscall

outprog:
	mov		rax, 0x2000001
	mov		rdi, 0
	syscall

section .data
	even_msg	db 'Even Number!'
	len1		equ	$ - even_msg

	odd_msg		db 'Odd Number!'
	len2		equ	$ - odd_msg

코드를 컴파일하고 실행하면, 다음의 결과를 확인할 수 있다.

Even Number!

ax 레지스터에 홀수를 넣으면

mov ax, 9h	; ax에 9를 넣는다.

프로그램은 다음과 같이 출력한다.

Odd Number!

레지스터의 모든 값을 클리어하기 위해서는 00H와 AND연산을 하면 된다.

OR 명령어

OR 명령어는 비트 단위 OR 연산을 처리하기 위해 사용된다. 비트 단위 OR 명령어는 같은 자리의 비트가 하나라도 1이라면 1을 반환한다. 그리고 두 비트가 모두 0이라면 0을 반환한다.

예를 들어,

             Operand1:    0101
             Operand2:    0011
------------------------------
After OR  -> Operand1:    0111

OR 명령은 하나 또는 그 이상의 비트를 설정하는데 사용할 수 있다. 예를 들어, AL 레지스터에 0011 1010이 들어있다고 가정하고, 하위 비트들의 값을 설정하고 싶다면, 0000 1111과 OR 연산을 하면 된다. 즉, FH

OR BL, 0FH	; BL을 0011 1111로 설정한다.

예제
다음 예제는 OR 연산을 설명한다. AL 레지스터에 5을 저장하고 BL 레지스터에 3을 각각 저장하고, 다음의 명령을 실행한다.

OR AL, BL

AL 레지스터에는 7이 저장된다.

❗️ 64비트 Intel macOS에서 동작하는 코드이다.

section .text
	global _main

_main:
	mov	al, 5
	mov	bl, 3
	or	al, bl
	add	al, byte '0'

	mov r10, result
	mov	[r10], al
	mov	rax, 0x2000004
	mov	rdi, 1
	mov	rsi, result
	mov	rdx, 1
	syscall

outprog:
	mov	rax, 0x2000001
	syscall

section .bss
	result resb 1

코드를 컴파일하고 실행하면, 다음의 결과를 얻을 수 있다.

7

XOR 명령어

XOR 명령어는 XOR 연산을 실행한다. XOR 명령어는 피연산자들의 같은 자리 비트가 서로 다를 경우에만 결과 비트를 1로 설정한다. 피연산자의 비트가 같다면(둘 다 0이거나 1), 결과 비트는 0으로 설정된다.
예를 들어,

             Operand1:    0101
             Operand2:    0011
------------------------------
After XOR -> Operand1:    0110

동일한 피연산자끼리 XOR 연산을 수행하면 피연산자가 0으로 초기화 된다. 이런 연산은 레지스터를 초기화하는데 사용한다.

XOR	EAX, EAX

TEST 명령어

TEST 명령어는 AND 명령어와 같은 동작을 한다. 그러나, AND 명령어와 다르게, 첫 번째 피연산자를 변경하지 않는다. 그래서, 레지스터에 있는 숫자가 짝수인지 홀수인지 확인하고자 한다면, 원본 숫자를 변경하지 않는 TEST 명령어를 사용할 수 있다.

TEST AL, 01H
JZ EVEN_NUMBER

NOT 명령어

NOT 명령어는 비트 단위 NOT 연산을 실행한다. NOT 명령어는 피연산자의 비트를 반대로 바꾼다. 피연산자는 레지스터나 메모리에 위치한다.

예를 들어,

             Operand1:    0101 0011
After NOT -> Operand1:    1010 1100

출처

tutorialspoint.com

0개의 댓글