[Assembly] 03 (사칙연산, Shift & Logical연산)

dev.kelvin·2024년 7월 3일

Assembly

목록 보기
3/5
post-thumbnail

1. 사칙연산

정수를 받아 변수,레지스터에 넣고 출력하려면?

    GET_DEC 1, al
    GET_DEC 1, num
   
    PRINT_DEC 1, al
    
    NEWLINE
    
    PRINT_DEC 1, num
    
section .bss
    num resb 1

GET_DEC는 Decimal값을 원하는 레지스터, 변수에 넣을 수 있는 명령어이다
뒤에는 크기, 원하는 레지스터 or 변수를 써준다

PRINT_DEC는 Decimal값을 Output에 출력시켜주는 명령어이다
뒤에는 크기, 원하는 레지스터 or 변수를 써준다

NEWLINE은 한 줄 띄워주는 명령어이다

다음은 1,2를 입력받아 al, num에 넣어주고 출력한 결과이다

어셈블리에서의 사칙연산

    add al, num ;crash발생
    add al, [num]

add a, b는 (a = a + b)를 의미한다
a는 레지스터 or 메모리, b는 레지스터 or 메모리 or 상수가 가능하다
이때 a, b 둘다 메모리로는 연산이 불가능하다

add al, 1 ;결과는 2가 나온다

이때 add al, num으로 계산 시 크래시가 발생한다
num은 메모리주소이기 때문에 1byte짜리 al에 넣으면 크래시가 발생하는 것이다

따라서 실제 메모리 주소에 있는 value값을 더해줘야 한다

다음과 다양하게 레지스터, 메모리 연산이 가능하다

    add al, bl ;레지스터 + 레지스터
    
    PRINT_DEC 1, al    
    
    NEWLINE
    
    add [num], byte 1 ;변수(메모리) + 상수
    
    PRINT_DEC 1, [num]    
    
    NEWLINE
    
    add [num], al ;변수(메모리) + 레지스터
    
    PRINT_DEC 1, [num]    
    
    NEWLINE

변수(메모리) + 상수 시 값 앞에 레지스터 or 변수의 크기를 명시해주어야 한다

위 코드를 빌드해보면 결과는 3,1,4가 나오게 된다

빼기 연산을 하고 싶다면 add대신 sub를 사용해주면 된다

어셈블리에서 곱셈과 나눗셈

곱셈연산은 mul 레지스터로 한다
mul bl을 하게되면 자동으로 al bl이 되며 결과값은 ax에 저장된다
mul bx를 하게 되면 자동으로 ax
bx가 되며 결과값 상위 16비트는 dx, 하위 16비트는 ax에 저장된다

    ;5 * 8을 어셈블리로 연산해보자
    
    mov ax, 0
    mov al, 5
    mov bl, 8
    mul bl

결과값은 40으로 나오게 된다

나눗셈 연산은 div 레지스터로 한다
div bl을 하게 되면 ax / bl이 되며 몫은 al, 나머지는 ah에 저장된다

    ;100 / 3을 어셈블리로 연산해보자
    
    mov ax, 100
    mov bl, 3
    div bl
    
    PRINT_DEC 1, al
    NEWLINE
    mov al, ah
    PRINT_DEC 1, al
    ;PRINT_DEC 1, ah ;ah레지스터는 PRINT_DEC로 출력이 불가능함

결과값은 33, 1이 나온다

2. Shift, Logical 연산

Shift연산이란?

Shift연산은 Bit단위로 좌 우로 이동시키는 연산을 의미한다

    mov eax, 0x12345678
    PRINT_HEX 4, eax
    NEWLINE
    
    shl eax, 8
    PRINT_HEX 4, eax
    NEWLINE
    
    shr eax, 8
    PRINT_HEX 4, eax
    NEWLINE

shl로 좌측, shr로 우측시프트가 가능하다 이때 레지스터 or 변수를 써주고 얼마나 시프트 할 지 값을 써준다

위 코드를 빌드해보면 다음과 같은 결과가 나오게 된다

코드를 계산기로 확인해보자, 다음은 0x12345678을 비트로 나타낸 그림이다

이 비트를 좌로 8 시프트 시키면 다음과 같이 나오게 된다, 결과값을 HEX로 확인했을 때 코드의 결과값과 같은 걸 확인할 수 있다

다음은 다시 우로 8 시프트 시킨 그림이다, 결과값은 마찬자기로 코드의 결과값과 같다

Shift연산은 왜 하는걸까?

우선 한번 좌측 Shift할 때 마다 한 칸이 이동하기 때문에 결과값은 2배가 되게 된다, 마찬가지로 한 칸 우측 Shift는 1/2가 된다

이렇게 2의 배수를 곱하거나 나눌 때 Shift연산으로 쉽게 할 수 있다
어셈블리에서는 나눗셈 곱셈이 복잡하기 때문에 2의 배수 곱셈, 나눗셈은 Shift연산으로 처리하는게 더 쉽다
(C++에서도 내부적으로 2의 배수 곱셈, 나눗셈 연산은 Shift연산으로 처리된다)

추가로 게임서버를 예로 들어보자

게임 서버는 Object를 ObjectID로 구분한다, 이 ObjectID를 만들 때 64bit를 사용한다고 가정하면 각 bit별 데이터가 존재할 것이다, 이때 이 데이터를 변경하기 위해서는 값을 직접 넣는것보다 bit를 Shift해서 제어하는게 더 효율적으로 사용할 수 있다

Logical 연산이란?

논리연산에는 not, and, or, xor가 존재한다

조건 A, B가 있을 때

not A는 A가 true면 false, false면 true로 만든다

A and B는 A도 true, B도 true면 true, A,B둘 중 하나라도 false면 false다

A or B는 A,B둘 중 하나라도 true면 true, A,B둘 다 false면 false다

A xor B는 둘이 같으면 false, 다르면 true다

이러한 논리 연산은 bit단위에서도 사용이 가능하다


이렇게 비트 쌍이 있다고 가정할 때 (위, 아래) 1은 true, 0은 false이기에 위의 논리연산에 적용이 가능하다

예를들어 위쪽 bit와 아래쪽 bit를 and연산하게 되면 다음과 같이 나오게 된다

이러한 논리 연산은 C++, Python등 프로그래밍 언어에는 무조건 존재한다

assembly에서 논리연산을 적용해보자

    mov al, 0b10010101
    mov bl, 0b01111100
    
    and al, bl
    or al, bl
    xor al, bl
    not al, bl

assembly언어로 단순히 and, or, xor, not 뒤에 비교할 2개를 넣어주면 된다

간단하게 and만 예측해보자, al and bl은 0b00010100이 되고 이를 HEX로 변환하면 0x14가 된다

PRINT_HEX로 확인 했을 때 14가 나오는걸 확인할 수 있다

Logical 연산은 어디에 사용할까?

Logical연산은 대표적으로 bitflag에 자주 사용된다

이런 비트가 있다고 가정해보자

프로그래머는 비트 단위에 의미를 부여할 수 있다 예를 들면 lol에서 cc기를 예로 들어보자 순차적으로 슬로우, 스턴, 에어본, 수면이라고 의미를 부여 했을 때, 위의 비트에서는 슬로우, 에어본 상태가 된다 이때 해당 캐릭터가 슬로우, 에어본 상태인지 확인하기 위해서 And를 사용할 수 있다 -> 1010과 and로 논리연산을 해서 true면 슬로우, 에어본 상태인 것이다

xor는 하나의 값을 xor하고 다시 xor하면 원복되는 특징을 가진다, 이러한 특징을 암호학에서 유용하게 사용할 수 있다
예를들어 value를 xor로 암호화 후 다시 복원 시 xor로 원래 value로 복원이 가능하다

또한 xor를 같은 대상끼리 하면 0 (false)이 나오게 된다 이는 대상이 같기 때문에 0 (false)으로 나오게 되는 것이다

xor rax, rax

assembly에서 기본적으로 있는 이 코드는 rax에 0을 넣는다는 의미이다 (mov rax, 0)
이 코드는 C++에서 return 0과 같은 의미이다

mov rax,0보다 xor rax,rax는 비트단위 연산이기 때문에 더 빠르다 따라서 C++에서도 0 대입 시 내부적으로는 이렇게 처리되는 것을 확인할 수 있다

profile
GameDeveloper🎮 Dev C++, DataStructure, Algorithm, UE5, Assembly🛠, Git/Perforce🌏

0개의 댓글