어 셈 블 리
-
어셈블리어 : 기계어에서 한 단계 위의 언어이며 기계어와 함께 단 둘뿐인 저급언어.
- 인라인 어셈블리를 통하여 직접적으로 어셈블리 언어를 입력하여, 원하는 어셈블리 코드를 짤 수 있지만,
32bit만 가능하다. 그렇기 때문에, 코드를 개발하는 단계에서 어셈블리 명령어가 깔끔하게 나오도록 코드를
짜려고 노력하는 습관을 들어야 한다.
CPU 레지스터
-
레지스터 : CPU 내부에서 처리할 명령어나 연산의 중간 값 등을 일시적으로 기억하는 임시 기억장소.
- Visual Studio 레지스터
EAX = 00ECC003 |
eax ( Extended Accumulator Register ) : 산술, 논리 연산에 사용하는 레지스터. |
EBX = 010B3000 |
ebx ( Extended Base Register ) : ESI, EDI와 결합하여 인덱스에 사용된다. |
ECX = 00ECC003 |
ecx ( Extended Counter Register ) : 반복문 등의 카운팅을 위한 레지스터. |
EDX = 00000001 |
edx ( Extended Data Register ) : 입, 출력 포인터 값을 저장. |
ESI = 00EC1325 |
esi ( Extended Source Index ) : 데이터 복사시 원본 주소 |
EDI = 012FF7AC |
edi ( Extended Destination Index ) : 데이터 복사시 목적지 주소 |
EIP = 00EC1788 |
eip ( Extended Instruction Pointer ) : 확장된 명령 지시자 |
ESP = 012FF6C8 |
esp ( Extended Stack Pointer ) : 현 스택의 포인터. |
EBP = 012FF7AC |
ebp ( Extended Base Pointer ) : 현 스택 프레임의 시작 주소. |
- 32bit 컴파일러의 경우에는 E ( Extended ) 가 앞에 붙지만, 64bit 컴파일러의 경우에는 R 이 붙는다.
지 역 변 수
-
지역변수는 STACK 메모리를 사용한다. ( 기본적으로 1MB로 설정 된다. )
- 이 때, 다음과 같은 코드를 Debug, Release 모드로 확인 후 비교 해 보겠다.
#include <stdio.h>
void Test() {
int x, y;
x = 0;
}
int main() {
int x = 0;
int y = -1;
Test();
y = x;
return 0;
}
-
Debug
int main() {
00541760 push ebp
00541761 mov ebp,esp
00541763 sub esp,0D8h
00541769 push ebx
0054176A push esi
0054176B push edi
0054176C lea edi,[ebp-0D8h]
00541772 mov ecx,36h
00541777 mov eax,0CCCCCCCCh
0054177C rep stos dword ptr es:[edi]
0054177E mov ecx,offset _DF75C5A9_어셈블리02@cpp (054C003h)
00541783 call @__CheckForDebuggerJustMyCode@4 (0541208h)
int x = 0;
00541788 mov dword ptr [x],0
int y = -1;
0054178F mov dword ptr [y],0FFFFFFFFh
Test();
00541796 call Test (0541014h)
y = x;
0054179B mov eax,dword ptr [x]
0054179E mov dword ptr [y],eax
return 0;
005417A1 xor eax,eax
}
005417A3 pop edi
005417A4 pop esi
005417A5 pop ebx
005417A6 add esp,0D8h
005417AC cmp ebp,esp
005417AE call __RTC_CheckEsp (0541212h)
005417B3 mov esp,ebp
005417B5 pop ebp
005417B6 ret
- Release
int x = 0;
int y = -1;
Test();
y = x;
return 0;
007F1000 xor eax,eax
}
007F1002 ret
Debug와 Release 두 동작의 차이가 확연히 나오는 것을 볼 수 있다.
Debug의 경우에는 안전 장치가 적용되어,
#include <stdio.h>
int main() {
int x = 0;
int y = -1;
printf(" &x - &y : %d \n", (int)&x - (int)&y);
return 0;
}
위의 코드를 돌려봤을 경우,
Debug : 12, Release : 4 가 나온다.
int가 4byte일 때, 보통은 4가 나오는 결과를 생각한다.
하지만, Debug모드에서는 변수의 앞과 뒤에 4byte의 정보를 추가하기 때문에 이러한 결과가 나온다.
|
x |
|
|
y |
|
이런 결과가 나올 것이다. 이것을 확인 해보자.
32bit에서 스택의 경우에는 아래에서 위로 올라가는 형식으로 데이터를 관리한다.
x의 경우에는 0x0133F998 ebp - 0Ch // 12
y의 경우에는 0x0133F98C ebp - 18h // 24
* h의 경우에는 16진수 라는 걸 표현
위의 방식으로 저장된다.
이것을 제외하고도 Debug에서 사용하는 안전장치 때문에 성능이 느릴 수 있다.
'[ 공 부 ] > [ C ]' 카테고리의 다른 글
[ C ] 메모리의 종류 ( 물리적 관점 ) (0) | 2020.09.22 |
---|---|
[C] 스코프 ( Scope ) (0) | 2020.08.24 |
[ C ] SCE ( Short - Circuit Evaluation ) (0) | 2020.08.20 |
[ C ] 실수의 표현방식 (0) | 2020.08.12 |
[ C ] 데이터 표현의 단위 (0) | 2020.08.11 |