stack 구조, 어셈블리 (MASM, 코드 분석)
test(4,3);
⇒ push 3
push 4
call test(→push eip, → call test)
|
printf |
|
|
test |
|
main stack ebp(old ebp) |
함수 호출 시 반드시 필요한 영역(overhead) | |
ret | ||
4 | ||
3 | ||
main |
|
← esp: main
|
B |
| |
A | ||
|
stack ebp RET(retrurn address)
init |
← ebp: main
|
- disassemble
test |
return |
push ebp mov ebp, esp sub esp, 50h |
mov esp, ebp pop ebp ret |
→ test의 세 개의 코드를 entry code라 한다.
→ return의 세 개의 코드를 exit code라 한다.
→ 처음에 C에서 우리가 변수를 몰아 선언하듯이 esp도 메모리를 미리 일정부분 확보한 다. (sub esp, 50h)
※ stack 호출시 최소한 8byte의 메모리가 필요하다. 인자 2개가 4byte를 차지하는 것 이외에도 ret, old ebp가 들어가기 때문에
→ 즉, 함수를 너무 많이 호출하면 좋지 않다. 함수 호출을 통하여 2개의 인자(push 3, push 4) 이외에도 call test의 두가지 일(push eip, call test)가 발생하게 되기 때문.
→ ARM 칩의 경우에는 인자를 4개까지는 레지스터에 저장하므로 4개까지는 굉장히 빠르게 되지만 5개 부터는 메모리를 사용해야 하므로 속도가 급격히 느려진다.
→ 즉, stack 구조에서 인자는 없는게 사실상 가장 빠르다. 그러므로 최적화를 위해서는 인자의 개수를 너무 많이 사용하는 것은 조심 한다.
MASM 컴파일.
⇒ 컴파일 방법
1. 컴파일
ml /c /coff masm.asm
→ ml:microsoft assembler
→ /c 컴파일해라
→ /coff 공통 obj 파일을 생성해라
→ 실행파일
2. 링킹
link /subsystem:console /entry:embedded /out:실행파일.exe 실행파일.obj io.obj kernel32.lib
→ /subsystem:console(도스창에서 이기 때문에 console을 붙인다.)
→ /entry:embedded 함수가 시작점
→ /out: 최종적으로 만들어 내는 실행파일(.exe)
→ link 시킬 파일을 적는다.(실행파일.obj io.obj kernel32.lib)
3. 실행
실행파일.exe
※ C:\jbpup\Detmer에서
io.h io.obj kernel32.lib link.exe 를 복사해서 컴파일할 폴더에 붙이면 해당 폴더에서 컴파일 가능
.386 ; 386이상 호환, ‘.’은 특정 모델 명기.
.MODEL FLAT ; FLAT 메모리 방식.
ExitProcess PROTO NEAR32 stdcall, dxExitCode:DWORD
; ExitProcess → 기본으로 제공하는 함수.
; protov 선언.
; near32 → 32bit에 가깝다.
; stdcall → push 방법.
; dxExitCode:DWORD → 반환값이 4byte이다.
INCLUDE io.h
; C와 같은 역활
cr EQU 0dh ; cr EQU(equal) 0DH(→ hexa)
; #define cr 0x0D와 같다.(cr을 프로그램에서 0x0D로 대체한다.)
Lf EQU 0ah ; 0A와 위의 0D는 아스키 코드를 뜻한다.
.STACK 4096 ; stack을 4096만큼 선언하겠다.(stack을 1024칸 사용가능 하도록 확보하겠다. ※C에서는 자동으로 해주지만 어셈블리에서는 직접 해주어야 한다.)
.DATA ; 전역변수(어셈블리에서 전역변수를 선언했다.)
number1 DWORD ? ; 변수 이름, DWORD는 double word이므로 4byte
number2 DWORD ? ; ? 는 쓰레기값을 뜻한다.
prompt1 BYTE "Enter first number : ", 0 ; 1byte이며 “” 내부는 배열이 선언되어있다. 즉, 각 글자가(띄어쓰기 포함) 1byte씩의 크기를 가진다. ,0(Null)은 문자열에서의 Null과 같다. 어셈블리는 자동으로 문자열에 Null이 들어가지 않으므로 적어주어야 한다.
→ “kkk”라는 문자열이 있다면 C는 4byte 어셈블리는 3byte이다. C는 Null을 자동으로 포함하기 때문이다.
prompt2 BYTE "Enter second number : ", 0
string BYTE 40 DUP (?) ; C에서 char string[40];과 같다. 즉, 초기화 안된 string을 넣었으므로 쓰레기값 ‘?’ 상태이다. DUP - 40에 ?를 복사해 넣어라. 즉, 40byte에 쓰레기값이 복사된다.
label1 BYTE cr, Lf, "The Sum is " ; C에서 "\r\rthe sum is"인데 어셈블리에서 개행문자를 지원하지 않으므로 cr, lt를 이용한다. 줄을 바꾼다.
sum BYTE 11 DUP (?) ; FFFFFFFF가 10진수 열자리이므로 그 이상의 값을 주었다.
BYTE cr, Lf, 0 ; 여기까지 변수(지역)가 총 7개
.CODE ; 코드영역의 시작을 선언
_embedded: ; 어셈블리 외부에서 쓰는 명령은 _(언더바)를 붙인다.
; 함수의 시작을 알린다.(임베디드 함수가 여기서 시작한다.-함수의 본체)
output prompt1 ; 어셈블리 문법이 아니다.(메크로), 뒤에것을 출력해준다.(표준이 아니며 교육용으로 선언된 것. printf와 비슷하다.)
input string, 40 ; 입력을 받는다. 문자열을 40 글자만큼 입력받을 수 있다.
atod string ; ASCII to decimal - 아스키를 10진수로 바꾼다. 그리고 eax라는 레지스터에 저장한다.(atod역시 메크로)
mov number1, eax ; eax의 값을 number1에 집어넣어라. mov는 뒤에서 앞으로 대입하라.(assembly 에서는 전송이라는 뜻)
output prompt2
input string, 40
atod string
mov number2, eax
mov eax, number1
add eax, number2 ; add - 덧셈하다. C로 표현하면 eax = eax+number2;와 같다. 즉, number1+number2를 eax에 넣는 것.
dtoa sum, eax ; decimal to ASCII 10진수를 아스키로 바꾼다.
output label1 ;
INVOKE ExitProcess, 0
PUBLIC _embedded ; 위와 현재의 embedded는 C의 { }와 같다.
END ; 전체 소스가 끝났다는 뜻.
- 실습 (Hello world!!)
.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dxExitCode:DWORD
INCLUDE io.h
cr EQU 0dh
Lf EQU 0ah
.STACK 4096
.DATA
prompt1 BYTE "Hello world!!", 0 ; 전역변수
; 어셈블리어 코드 주석은 ;(세미콜론)이다.
; 어셈블리는 “” 내의 문자에서 C처럼 null을 자동으로 첨부하지 않기 때문에 ,0을 표시해 주어야 한다.
.CODE
_embedded: ; 엔트리 포인트
output prompt1 ; output은 실제 어셈블리에 있는게 아니라 메크로로 만들어 둔 것이다. intput도 마찬가지. 이해를 돕기 위한 것으로 실재로는 printf와 scanf를 뜻한다.
INVOKE ExitProcess, 0 ; INVOKE는 exit 함수를 뜻하는 것으로써 어디서든 exit를 호출하게 되면 강제로 종료시키게 된다.
PUBLIC _embedded
END
'내장형 하드웨어 > C언어' 카테고리의 다른 글
수학 함수 (math.h), 난수 생성 함수(랜덤 함수) rand - srand, seed, time(NULL) (0) | 2011.05.06 |
---|---|
함수 전달의 3가지 - 참조(reference), 주소(address), 값(value), 재귀함수, touch, ifndef (0) | 2011.05.04 |
visual studio 6.0 debug mode - stack (esp, sbp, eip) (0) | 2011.04.28 |
assembler - stack의 이해 (ebp, esp, eip) (0) | 2011.04.27 |
메모리 영역 (Code, Data, BSS, HEAP, Stack), Little Endian, Stack의 이해 (1) | 2011.04.26 |