컴퓨터구조
[컴퓨터 구조] 어셈블리어 1. 기본 문법과 명령어
greenkang
2023. 5. 1. 01:23
📗 어셈블리어 Assembly
- 0과1로 이루어진 기계어와 1대1로 대응되는 명령어로 이루어진 저급언어
- 모든 기계마다 동일하지 않음
📗 어셈블리어를 알아야 하는 이유
- 문제 해결 범위 증가 : 고수준의 언어로 작성된 코드에서 문제점이 보이지 않을 때, 컴파일된 어셈블리어 코드를 보고 문제의 원인을 파악할 수 있습니다.
- 개발 도구에 대한 이해 향상 : 고수준 언어로 코드를 작성하고 실행하면 바로 실행결과가 나옵니다. 어셈블리어를 알아두면 고수준언어로 코드를 작성하고 빌드하면 어떻게 변환되어 컴퓨터에게 전달되는지 과정을 이해할 수 있습니다.
- 함수 호출 방식에 대한 깊은 이해 : 어셈블리어를 알아두면 전역변수와 지역변수가 어디에 저장되는지, 함수를 호출 했을 경우 프로그램의 실행 흐름이 어떻게 되는지 보다 깊이 이해할 수 있습니다.
한 마디로 정리하자면
어셈블리어를 알아두면 코드의 실행 프로세스를 컴퓨터와 가까운 레벨에서 이해할 수 있고,
문제점이 발생했을 경우 더욱 폭 넓게 원인을 파악할 수 있습니다 🙂.
📗 어셈블리어 기본 문법 (Intel 문법 / AT&T 문법)
CPU마다 고유한 어셈블리어를 사용합니다.
따라서 CPU마다 어셈블리어의 기본 문법이 다릅니다.
여기에서는 Intel과 AT&T 어셈블리어 기본 문법을 다뤄보겠습니다.
- 숫자 표기 방식 / 레지스터 표기 방식
Intel : 숫자와 레지스터 모두 그대로 표기합니다.
AT&T: 숫자에는 앞에 $을 붙이고, 레지스터에는 %를 붙여 사용합니다.
- 명령어 수행 방식
Opcode (명령어) | Operand1 (피 연산자1 / 레지스터) | Operand2 (피 연산자2 / 레지스터) |
ADD | EAX | EBX |
Intel :EBX의 값을 EAX에 더한다.
AT&T : EAX의 값을 EBX에 더한다.
즉,
Intel에서는 Operand2가 Source, Operand1이 Destination
AT&T에서는Operand1가 Source, Operand2가 Destination 입니다.
📗 어셈블리에서 사용되는 레지스터 종류
📌 레지스터
- CPU의 요청을 처리하는 데이터의 임시 공간
- 공간은 작고, 비싸지만 CPU와 직접 연결 되어 있어서 연산 속도가 빠르다.
- CPU는 자체적으로 데이터를 저장할 수 없으므로 레지스터를 사용하여 연산처리를 하고, 데이터의 주소를 설정한다.
- 컴퓨터의 장치들을 제어한다.
- 32비트는 레지스터의 처음이 E로 시작, 64비트는 R로 시작한다.
📌 범용 레지스터
데이터 임시 저장, 산술 및 논리 연산, 데이터의 주소를 지정 등등 여러가지 목적으로 사용되는 레지스터
EAX (Accumulator) |
산술연산에 자동으로 사용되며, 함수의 반환값을 처리할 때에도 사용된다. |
EBX (Base Register) |
주소 지정에 사용 된다. 산수 변수를 저장한다. |
ECX (Counter Register) |
반복에서 반복 Count 역할을 수행한다. |
EDX (Data Register) |
EAX를 보조하는 역할을 한다. 나누기 연산을 할 때, 몫은 EAX 나머지는 EDX에 저장한다. |
📌 인덱스 레지스터
복사나 비교를 할 경우 출발지 주소를 저장하는 레지스터
ESI (Source Index) |
복사나 비교를 할 경우 출발지 주소를 저장한다. |
EDI (Destination Index) |
복사나 비교를 할 경우 목적지 주소를 저장한다. |
📌 포인터 레지스터
Base Pointer : 기본적으로 스택 내의 주소를 지시하지만 데이터에 대한 베이스 주소를 저장한다.
Stack Pointer : 스택 조작을 위해 사용하는 레지스터. 프로그램 실행중에 데이터의 주소를 저장한다.
EIP (Program Counter) |
다음 실행할 명령어의 주소를 저장한다. 현재 명령어의 실행이 끝나면 이 레지스터에 있는 주소에 저장되어 있는 명령어를 실행한다. |
ESP (Stack Pointer) |
Stack Pointer의 가장 최근에 저장된 공간의 주소를 저장한다. |
EBP (Basw Pointer) |
Stack Pointer의 처음 저장된(기준점, 바닥) 공간의 주소를 저장한다. |
📗 어셈블리 명령어
주로 사용되는 명령어에 대해서만 작성하겠습니다😋.
명령어 | 예제 | 설명 |
push | push eax | eax의 값을 스택에 저장 |
pop | pop eax | 스택 가장 상위에 있는 값을 꺼내서 eax에 저장 |
mov | mov eax, ebx | 메모리나 레지스터의 값을 이동 |
inc / dec | lnc eax / dec eax | eax의 값을 1증가시킨다 (++) eax의 값을 1감소시킨다 (--) |
add / sub | add eax, ebx / sub eax, ebx | 레지스터나 메모리의 값을 덧셈 하거나 뺄셈 피 연산자 1과 2를 뎃셈 피 연산자 1과 2를 뺄셈 |
call | call proc | 프로시져를 호출 |
ret | ret | 호출했던 바로 다음 지점으로 이동 |
cmp | cmp eax, ebx | 피 연산자 1, 2 비교 |
jmp | jmp proc | 특정한 곳으로 분기 |
int | int $0x80 | OS에 할당된 인터럽트 영역을 system call |
nop | nop | 아무 동작도 하지 않는다. (No Operation) |