Notice
Recent Posts
05-06 01:42
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Today
Total
관리 메뉴

프로그래밍 잡화점

0 - 3 기본적인 Assembly 개념 - 문법과 instruction Part 2 본문

Assembly

0 - 3 기본적인 Assembly 개념 - 문법과 instruction Part 2

Luana7 2023. 4. 13. 23:46

4. 비트 연산자

 

비트 연산에도 생각보다 많은 명령어가 존재하지만, 기본적인 것만 알아보고 가자.

 

shl, shr, not, and, or, xor

 

사용법은 간단하다. not을 제외하고 operand를 2개 갖는다.

not은 1개의 operand를 갖는다.

 

shl 은 shift left의 약자로 C에서 <<와 같고

shr 은 shift right의 약자로 C에서 >>와 같다.

 

나머지 연산자의 경우에는 일반적으로 아는 그 연산자들이다.

 

 

5. 조건과 분기

 

이제 가장 많이 쓰게 될 조건과 분기에 대해서 알아보자.

 

call도 분기에 속하지만, 설명할 내용이 많아 나중에 설명할려고 한다.

 

일단 조건문을 구성할 때 쓰이는 녀석엔 두가지가 있다.

cmp와 test란 녀석인데

 

cmp는 이름부터 유추할 수 있듯이 compare의 약자이다.

cmp op1, op2

cmp가 if라고 생각해 op1이 조건, op2가 라벨이라 생각했다면 큰 오산이다!

 

어셈블리는 특이하게 조건과 분기가 나눠져있다.

 

해당 코드가 수행되면 op1 - op2를 수행하고 결과에 따라서 Flag Register을 설정한다.

단순히 이 작업이 끝이다. "cmp는 분기를 수행하지 않는다!"

 

test도 마찬가지로 Flag Register을 설정해준다.

그러나 작동 방식이 조금 다르다.

 

cmp의 경우 op1 - op2를 수행했다면, test의 경우 op1 & op2를 수행한다.

 

프로그램을 역어셈 해보다보면 test eax, eax와 같은 형태가 많이 보일 것이다.

같은 레지스터 끼리 & 연산해서 뭐하냐 싶겠지만

이는 eax가 0인지를 검사하는 코드로써 작동한다.

 

test는 and의 결과에 따라서 0이면 Z Flag를 1로, 1이면 Z Flag를 0으로 설정한다.

이로서 간단히 판단하려는 레지스터가 0(거짓)인지 0외의 수(참)인지를 판단 할 수 있는 것이다.

 

 

그럼 다음으로 분기에 대해서 보자. 분기에는 여러가지가 존재한다.

가장 기본적인 형태인 jmp가 있는데, 아무 조건 없이 단순히 점프한다.

C에서의 goto를 생각하면 편할 것이다.

 

그 뒤로는 조건을 갖는 분기가 있는데

JE, JNE, JL(JNGE), JLE(JNG), JG(JNLE), JGE(JNL) 가 있다.

 

보자마자 외워야겠다는 생각이 들텐데, 단순히 생각해보면 외울것도 없다.

JE는 Jmp if Equal, JNE는 Jmp if Not Equal

JL은 Jump if Less, JLE는 Jmp if Less Eqaul

JG는 Jump if Greater, JGE는 Jump if Greater Equal

 

단순히 이름을 줄였을 뿐이다.

원래라면 Flag 상태에 따라서 조건 분기가 결정되지만, 단순히 이름만 가지고 추측을 해볼 수 있을 것이다.

 

 

간단한 문제를 통해서 복습해보자.

 

if (eax > ebx) {
    eax = ebx;
}

// Do something

이 코드를 어셈블리로 치환한다면 어떻게 될까?

더보기
    cmp eax, ebx
    jg if1

    jmp endif1

if1:
    mov eax, ebx
    jmp endif1   ; elseif가 존재한다면 필요할 수도 있다.
    
endif1:
	; Do something

이런식의 형태가 될 것이다. 구현의 형태는 어떤식으로 구상하냐에 따라서 달라질 수도 있다.라벨 수를 줄이고자 한다면 jg대신 jle를 넣어서 만들 수도 있는 것이다.

 

두번째 문제

간단한 for문을 만들어보자

for (ecx = 0; ecx < 5; ecx++) {
    // Do something
}
더보기
    mov ecx, 0

for1:
    cmp ecx, 5
    jge for1_end
    
    ; Do something
    
    ; inc와 dec는 ++, --역할을 해주는 instruction이다.
    inc ecx
    jmp for1
    
for1_end:

이런식으로 작성될 것이다.

물론 실제로 for문을 구상할 때에는 ecx를 사용한다면 push, pop을 통해서 ecx의 값을 보존해줘야 하며, 그게 아니라면 stack 또는 data section에 할당된 변수를 이용해 구현하는게 좋다.

 

 

 

원래는 역어셈을 위한 어셈블리 강좌였으나, 어셈블리에 관한 지식도 정리할 겸 단순 강좌로 바뀌게 되었다.

다음 포스팅에서는 call에 대해서 배워볼까 한다.

Comments