기본 형식 : [operation dst, src]
operation - 명령
dst - 목적지 : 연산의 결과가 저장 되는 곳으로 레지스터나 메모리가 온다.
src - 출발지 : 레지스터, 메모리, 상수 모두 가능하다.
dst와 src의 크기는 동일해야함!!
범용 레지스터
EAX(ExtendAccumulatorRegister): 사칙연산등 산술 연산에 사용되며, 함수의 반환값을 처리할 때도 사용됨
EBX(ExtendBaseRegister): 간접 번지 지정에 사용되며, 산수 및 변수를 저장함
ECX(ExtendCountRegister): 반복에서 카운트 역할을 수행함
EDX(ExtendDataRegister): EAX를 보조하는 역할을 수행함
인덱스 레지스터
ESI(ExtendSourceIndex): 복사나 비교를 할 경우 출발지 주소를 저장하는 레지스터
EDI(ExtendDestinationIndex): 복사나 비교를 할 경우 목적지 주소를 저장하는 레지스터
포인터 레지스터
EIP(ExtendInstructionPointer): 다음에 실행할 명령어의 주소를 가지고 있는 레지스터
ESP(ExtendStackPointer): Stack pointer의 가장 최근에 저장된 공간의 주소를 저장하는 레지스터
EBP(ExtendBottomPointer): Stack pointer의 기준점(바닥)을 저장하는 레지스터
자주 사용되는 명령어
- push: 값을 스택에 저장
ex) push eax
- pop: 스택 가장 상위에 있는 값을 꺼내어 레지스터에 저장
ex) pop eax
- mov: 메모리나 레지스터의 값을 이동하거나 대입
ex) mov eax, ebx -> eax = ebx
ex) mov dword[ebx], 0x12 -> ebx가 가리키는 포인터 위치에 0x12을 대입 (대괄호는 포인터라는 의미)
- inc: 값을 1 증가 시킴
ex) inc eax
- dec: 값을 1 감소 시킴
ex) dec eax
- add : 레지스터나 메모리의 값을 덧셈
ex) add ecx, ebx -> ecx += ebx
- sub : 레지스터나 메모리의 값을 뺄셈
ex) sub eax, 20 -> eax -= 20
- call: 프로시저 호출
- lea: 주소 값을 대입
ex) lea edi, dword ptr [ebp+8]
- ret: 호출했던 바로 다음 지점으로 이동
- cmp: 두 레지스터의 값을 비교
- jmp: 특정한 곳으로 분기
- jle: 비교 결과 값이 '0'이거나(ZF=1), 작을경우 해당 주소로 점프
- int: OS의 인터럽트 system call
- nop: 아무 동작 안함
예제 코드
int func(int a, int b)
{
return a - b;
}
int main(void)
{
int a = 10;
int b = 20;
int c = 30;
int d = (c - a);
int e = ++a;
int f = b--;
int g = a > b ? a : b;
int h = func(b, a);
system("pause");
return 0;
}
어셈블리 코드
00CE11E5 jmp 00CE29A0
int func(int a, int b)
{
00CE29A0 push ebp // ebp 값을 스택에 push
00CE29A1 mov ebp,esp // ebp = esp
00CE29A3 sub esp,0C0h // esp -= 0C0h
00CE29A9 push ebx // ebx 값을 스택에 push
00CE29AA push esi // esi 값을 스택에 push
00CE29AB push edi // edi 값을 스택에 push
00CE29AC lea edi,[ebp+FFFFFF40h] // edi에 ebp+FFFFFF40h의 값 대입
00CE29B2 mov ecx,30h // ecx = 30h
00CE29B7 mov eax,0CCCCCCCCh // eax = 0CCCCCCCCh
00CE29BC rep stos dword ptr es:[edi] // eax 값을 edi가 가리키는곳에 ecx 반복 복사
00CE29BE mov ecx,0CEE091h // ecx = 0CEE091h
00CE29C3 call 00CE1415
return a - b;
00CE29C8 mov eax,dword ptr [ebp+8] // eax = a;
00CE29CB sub eax,dword ptr [ebp+0Ch] // a -= b;
}
int main(void)
{
00CE2A00 push ebp
00CE2A01 mov ebp,esp
00CE2A03 sub esp,124h
00CE2A09 push ebx
00CE2A0A push esi
00CE2A0B push edi
00CE2A0C lea edi,[ebp+FFFFFEDCh]
00CE2A12 mov ecx,49h
00CE2A17 mov eax,0CCCCCCCCh
00CE2A1C rep stos dword ptr es:[edi]
00CE2A1E mov ecx,264092h
00CE2A23 call 00CE1415
int a = 10;
00CE2A28 mov dword ptr [ebp-8],0Ah // 0A = 10
int b = 20;
00CE2A2F mov dword ptr [ebp-14h],14h // 14 = 20
int c = 30;
00CE2A36 mov dword ptr [ebp-20h],1Eh // 20 = 30
int d = c + a;
00CE2A3D mov eax,dword ptr [ebp-20h] // eax레지스터에 c값 대입
00CE2A40 add eax,dword ptr [ebp-8] // eax레지스터에 a값 덧셈
00CE2A43 mov dword ptr [ebp-2Ch],eax // d에 eax레지스터값 대입
int e = ++a;
00CE2A46 mov eax,dword ptr [ebp-8] // eax레지스터에 a값 대입
00CE2A49 add eax,1 // eax레지스터에 1 덧셈
00CE2A4C mov dword ptr [ebp-8],eax // a에 eax레지스터값 대입
00CE2A4F mov ecx,dword ptr [ebp-8] // ecx레지스터에 a값 대입
00CE2A52 mov dword ptr [ebp-38h],ecx // e에 ecx레지스터값 대입
int f = b--;
00CE2A55 mov eax,dword ptr [ebp-14h] // eax레지스터에 b값 대입
00CE2A58 mov dword ptr [ebp-44h],eax // f에 eax레지스터값 대입
00CE2A5B mov ecx,dword ptr [ebp-14h] // ecx레지스터에 b값 대입
00CE2A5E sub ecx,1 // ecx레지스터에 1 뺄셈
00CE2A61 mov dword ptr [ebp-14h],ecx // ecx값 b에 대입
int g = a > b ? a : b;
00CE2A64 mov eax,dword ptr [ebp-8] // eax레지스터에 a값 대입
00CE2A67 cmp eax,dword ptr [ebp-14h] // eax레지스터와 b값 비교
00CE2A6A jle 00CE2A77 // cmp 결과가 0일경우(ZF=1) 해당 주소 점프
---------------------------------a > b가 참인 경우---------------------------------------
00CE2A6C mov ecx,dword ptr [ebp-8] // ecx레지스터에 a값 대입
00CE2A6F mov dword ptr [ebp+FFFFFEDCh],ecx // ebp+FFFFFEDC에 ecx레지스트값 대입
00CE2A75 jmp 00CE2A80 // 00256C70 점프
---------------------------------a > b가 거짓인 경우-------------------------------------
00CE2A77 mov edx,dword ptr [ebp-14h] // edx레지스터에 b값 대입
00CE2A7A mov dword ptr [ebp+FFFFFEDCh],edx // ebp+FFFFFEDC에 ecx레지스트값 대입
-----------------------------------------------------------------------------------------
00CE2A80 mov eax,dword ptr [ebp+FFFFFEDCh] // eax레지스터에 [ebp+FFFFFEDCh] 값 대입
00CE2A86 mov dword ptr [ebp-50h],eax // g에 eax레지스터값 대입
int h = func(b, a);
00CE2A89 mov eax,dword ptr [ebp-8] // eax레지스터에 a값 대입
00CE2A8C push eax // 스택에 eax레지스터값 저장
00CE2A8D mov ecx,dword ptr [ebp-14h] // ecx레지스터에 b값 대입
00CE2A90 push ecx // 스택에 ecx레지스터값 저장
00CE2A91 call 00CE11E5 // 00CE11E5 호출(이 주소에서 func로 jmp)
00CE2A96 add esp,8 //
00CE2A99 mov dword ptr [ebp-5Ch],eax //
system("pause");
00CE2A9C mov esi,esp
00CE2A9E push 25EE10h
00CE2AA3 call dword ptr ds:[00CED1B4h]
00CE2AA9 add esp,4
00CE2AAC cmp esi,esp
00CE2AAE call 002513D9
return 0;
00CE2AB3 xor eax,eax
}
'쿼리큘럼 개인적 정리' 카테고리의 다른 글
성능 측정 프로파일러 (0) | 2021.09.11 |
---|---|
메모리 누수 추적 라이브러리 (0) | 2021.09.11 |
CPU 캐시 메모리 (0) | 2021.09.10 |
윈도우 메모리구조와 메모리분석 기초 (0) | 2021.09.10 |
C 언어의 어셈블리 분석 (0) | 2021.09.10 |