어셈블리어의 개념
참조: kr wikipedia - 어셈블리어어셈블리어(영어: assembly language) 또는 어셈블러 언어(assembler language)는 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어이다.
어셈블리어는 1951년에 개발된 언어이다.
예엣날 예엣적 인간이 기계어를 더 쉽게 이해하기 위해 개발된 언어로,
기계어와 1대1 대응 관계이며 저급언어에 속한다. (기계어랑 어셈블리어 둘밖에 없음 ㅋㅋ)
기계어랑 어셈블리어는 1대1 대응 관계인데,
당시 기계어는 기계마다 달랐으므로 기계마다 어셈블리어도 조금식 다르게 된다.
최근에는 임베디드 분야의 발전으로 용량이 작은 어셈블리어가 다시 인기를 끌고 있다!!
어셈블리어의 비효율성
물론 어셈블리어는 기계어보다 훨씬 편하다.
아래 두 명령어가 같은 뜻이라고 생각해 보자.. 기계어 프로그래머는 전부 굇수였던게 분명하다;
addi $0, $1, 10
001000 00001 00000 0000000000001010
다만 어셈블리어가 그때 당시 좋았던 건 그렇다 쳐도 현재까지도 효율적이고 좋은 언어라고 할 수는 없다.
어셈블리어는 명령어가 굉장히 축약되어 있어 처음에 공부할 때 어려움이 많고,
동작 하나하나를 명령해야 하기 때문에 명령어 효율성이 떨어지며,
성능 자동판별 기능도 없기 때문에 속도 측면에서도 좋다고 할 수 없다.
냉장고에서 물을 꺼내 마시는 과정을 어셈블리어와 C언어로 비교해보자.
void 물마시기(void)
{
bool bOpen = 냉장고문열기();
if (bOpen)
{
물꺼내기();
마시기();
물넣기();
냉장고문닫기();
}
}
_asm {
냉장고앞으로가기
냉장고문잡기
냉장고문열기
문열기성공:
냉장고내부확인
손들기
냉장고안에넣기
물병잡기
물병꺼내기
뚜껑열기
물컵에따르기
컵손에들기
컵에든거마시기
컵내려놓기
손들기
뚜껑닫기
물병잡기
냉장고안에넣기
손꺼내기
냉장고문닫기
}
어셈블리어의 문법
어셈블리어의 명령어는 command [parameters]의 포맷을 지니고 있다.
이 중 command 부분을 opcode라고 부르고, [parameters]를 operand라고 한다.
operand는 두 개 이상이 올 수 있으며,
이 때 앞의 인자가 목적지(dest)가 되며 뒤의 인자가 출발지(src)가 된다.
- 조작 명령어 -
call : 함수 호출
ret : call로 호출한 함수를 종료하고 다음 명령줄로 이동
nop : 아무것도 하지 않음
jmp : 분기(라벨) 실행
조건 점프 명령어 : cmp 연산 결과에 따라 jmp
1) je : cmp A B 에서 A == B 일때 jmp
2) jne : cmp A B 에서 A != B 일때 jmp
3) ja : cmp A B 에서 A > B일 때 jmp
4) jb : cmp A B 에서 A < B일 때 jmp
5) jae : cmp A B 에서 A >= B일 때 jmp
6) jae : cmp A B 에서 A <= B일 때 jmp
- 데이터 전송 명령어 -
push : 스택에 값 넣기
pop : 스택에서 값 가져오기
mov : mov param1 param2에서 param2의 값을 param1에 대입
lea : lea param1 param2에서 param2의 주소를 param1에 대입
조건 점프 명령어 : cmp 연산 결과에 따라 jmp
- 산술 명령어 -
inc : 인자의 값 1 증가
dec : 인자의 값 1 감소
add : add param1 param2에서 param2의 값을 param1에 더함
sub : sub param1 param2에서 param2의 값을 param1에 뺌
cmp : cmp param1 param2에서 값을 비교할 때 사용; 위의 조건 점프 명령어와 같이 사용
test : test param1 param2에서 두 인자의 값을 AND 연산함.
명령어 개념 학습
cmp 명령어
cmp 명령어는 [dst]과 [src]의 값을 비교하여 포인터에 저장한다.
dst < src인 경우에는 ZF(Zero Flag)에 0을, CF(Carry Flag)에 1을 저장
dst > src인 경우에는 ZF(Zero Flag)에 0을, CF(Carry Flag)에 0을 저장
dst = src인 경우에는 ZF(Zero Flag)에 1을, CF(Carry Flag)에 0을 저장
jmp 명령어
jmp 명령어는 cmp 명령어 계산 결과(ZF, CF)에 따라 다른 파트로 이동한다.
JA | CF = 0 and ZF = 0 | dst > src |
---|---|---|
JAE | CF = 0 or ZF = 1 | dst >= src |
JB | CF = 1 | dst < src |
JBE | CF = 1 or ZF = 1 | dst <= src |
JC | CF = 1 | JB와 차이를 모르겠네요. |
JE | ZF = 1 | dst = src |
JZ | ZF = 1 | dst = src |
레지스터의 개념
레지스터는 프로세서에 있는 고속 메모리이다.
작은 데이터와 중간 결과 같은 값을 저장할 수 있기에, 어셈블리어에서는 변수처럼 사용한다.
범용 레지스터
범용 레지스터는 CPU 내에 위치해 있으며,
연산처리/연산결과/복귀주소 등 작은 데이터를 기억하는 레지스터이다.
1. 산술-논리 연산을 맡는 레지스터
EAX Accumulator Register |
가장 자주 사용하는 변수로, 사칙연산과 논리연산에서 주로 사용한다. |
EBX Base Register |
특별한 목적으로 만들어진 레지스터가 아니다. |
ECX Count Register |
C는 Count의 의미로써 사용되었다. 반복문에서의 idx 역할을 맡는다. |
EDX Data Register |
일반적으로 EAX와 함께 연동하여 사용한다. |
2. 메모리 주소를 저장하는 레지스터
EBP Base Point Register |
Stack의 첫 시작 주소를 저장한다. |
ESP Stack Pointer Register |
Stack의 끝 주소를 저장한다. |
ESI Source Index Register |
데이터 조작/복사 시 소스 데이터의 주소를 저장한다. |
EDI Destination Index Register |
데이터 복사 시 목적지의 주소를 저장한다. |
참고로 함수 앞에 _(언더바)를 붙이는 것은 규약이다!!
Comment