본문 바로가기

2. Reversing (리버싱)/2) 개념 정리

[2022.03.19] 어셈블리어, 레지스터

어셈블리어란?

어셈블리어(assembly language)는 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어이다.

0과 1의 이진수로 프로그램을 하는 기계어는 인간의 관점에서는 컴퓨터가 바로 읽을 수 있다는 점만 빼면 장점이 없는 언어이기 때문에 이를 보완하기 위해 나온 언어가 어셈블리어이다. 기계어와 명령어가 1:1로 대응되는 단어들로 구성되어 있으며 저급 언어는 컴퓨터와 가까운 언어이기 때문에 컴파일을 해도 간단한 명령으로 실행돼서 실행 속도가 굉장히 빠르다. 하지만 배우기가 어렵고 유지보수가 힘들다는 이유로 특수한 경우를 제외하고는 사용되지 않고 있다.

 

컴파일 vs 어셈블

고급언어로 작성한 원시 프로그램을 컴파일러가 기계어로 번역하는 작업을 컴파일(Complie)한다고 하고, 어셈블리어로 작성한 원시 프로그램을 어셈블러가 번역하는 작업을 어셈블(Assemble)한다고 한다.

 

어셈블리어의 명령어 형식

어셈블리어의 명령어 형식은 Label, OP, Operand로 구성된다.

Label : 데이터를 기억할 기억장소, 또는 분기할 위치, 기호 상수 등에 대한 기호를 기술하는 부분이다. (생략 가능)

OP : 명령어(OP-Code)를 기술하는 부분이다.

Operand : OP-code가 연산을 수행하기 위한 연산의 대상이 되는 Literal(상수,데이터)나 주소, Register 번호 등을 기술하는 부분이다.

 

 

어셈블리에서 사용되는 레지스터 종류 

레지스터란?

레지스터는 CPU의 요청을 처리하는 데이터의 임시공간이다. 레지스터는 공간이 작고 가격은 비싸지만 CPU에 직접 연결되어 있어서 연산 속도가 매우 빠르다는 장점이 있다. 32비트의 경우 레지스터의 처음이 E로 시작하고, 64비트의 경우 R로 시작한다.

 

범용 레지스터

EAX : 사칙연산 등 산술 연산에 자동으로 사용되며, 함수의 반환 값을 처리할 때도 사용된다.

EBX : 간접 번지 지정에 사용된다. 산수, 변수를 저장한다.

ECX : 반복(Loop)에서 반복 Count 역할을 수행한다.

EDX : EAX를 보조하는 역할을 한다. 예를 들어, 나누기를 진행할 경우 몫은 EAX에 나머지는 EDX에 저장된다.

 

인덱스 레지스터

ESI : 복사나 비교를 할 경우 출발지 주소를 저장하는 레지스터이다.

EDI : 복사나 비교를 할 경우 목적지 주소를 저장하는 레지스터이다.

 

포인터 레지스터

EIP : 다음에 실행할 명령어의 주소를 가지고 있는 레지스터이다. 현재 실행하고 있는 명령어가 종료되면 이 레지스터에 있는 명령어를 실행한다.

ESP : Stack Pointer의 가장 최근에 저장된 공간의 주소를 저장하는 레지스터이다.

EBP : Stack Pointer의 기준점(바닥 부분)을 저장하는 레지스터이다.

 

어셈블리어 - 자주 사용하는 명령어

명령어 예제 설명 분류
push push eax eax의 값을 스택에 저장 스택 조작
pop pop eax 스택 가장 상위에 있는 값을 꺼내서 eax에 저장 스택 조작
mov mov eax, ebx 메모리나 레지스터의 값을 옮길때 사용 데이터 이동
inc lnc eax eax의 값을 1증가시킨다 (++) 데이터 조작
dec dec eax eax의 값을 1감소시킨다 (--) 데이터 조작
add add eax, ebx 레지스터나 메모리의 값을 덧셈할때 쓰인다. 논리, 연산
sub sub eax, ebx 레지스터나 메모리의 값을 뺄셈할때 쓰인다. 논리, 연산
call call proc 프로시저를 호출한다. 프로시저
ret ret 호출했던 바로 다음 지점으로 이동 프로시저
cmp cmp eax, ebx 레지스터와 레지스터의 값을 비교 비교
jmp jmp proc 특정한 곳으로 분기 분기
int  int $0x80 OS에 할당된 인터럽트 영역을 system call 인터럽트
nop nop 아무 동작도 하지 않는다. (No Operation)

 

어셈블리어 예제 ( C언어 → 어셈블리어 )


#include<stdio.h>

int main() {
    int a = 1;
    int b = 2;
    int c = a + b;
    
    printf("%d", c);
}


 

C언어로 작성되어 있는 위의 코드를 어셈블리어로 번역하면 다음과 같다.

 


 push        ebp  
 mov         ebp,esp  
 sub         esp,0E4h  
 push        ebx  
 push        esi  
 push        edi  
 lea         edi,[ebp+FFFFFF1Ch]  
 mov         ecx,39h  
 mov         eax,0CCCCCCCCh  
 rep stos    dword ptr es:[edi]  
 mov         ecx,9AC003h  
 call        009A1316  
 mov         dword ptr [ebp-8],1  
 mov         dword ptr [ebp-14h],2  
 mov         eax,dword ptr [ebp-8]  
 add         eax,dword ptr [ebp-14h]  
 mov         dword ptr [ebp-20h],eax  
 mov         eax,dword ptr [ebp-20h]  
 push        eax  
 push        9A7D08h  
 call        009A10CD  
 add         esp,8  
 xor         eax,eax  
 pop         edi  
 pop         esi  
 pop         ebx  
 add         esp,0E4h  
 cmp         ebp,esp  
 call        009A123F  
 mov         esp,ebp  
 pop         ebp  
 ret  


참고 자료

https://coding-factory.tistory.com/651

 

[Assembly] 어셈블리어 기초 사용법 & 예제 총정리

어셈블리어란? 어셈블리어(assembly language)는 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어입니다. 전류가 흐른다 그렇지 않다로 구성되는 0과 1의 이진수로 프로그램을 하는 기계

coding-factory.tistory.com

 

https://coding-factory.tistory.com/304

 

[Assembly] 어셈블리어란 무엇인가?

어셈블리어란? 어셈블리어란 사용자가 이해하기 어려운 기계어 대신에 명령 기능을 쉽게 연상할 수 있는 기호를 기계어와 1:1로 대응시켜 코드화한 기호 언어입니다. 1. 어셈블리어로 작성한 원

coding-factory.tistory.com