외로운 Nova의 작업실

Assembly 언어 공부 - 27(스택 프레임) 본문

Programming/Assembly

Assembly 언어 공부 - 27(스택 프레임)

Nova_ 2022. 9. 10. 22:35

안녕하세요. 이번시간에는 스택 프레임에대해서 알아보도록 하겠습니다.

 

- 스택 프레임

스택 프레임은 스택안에서 함수에 의해 나눠진 공간을 의미합니다. 즉 main 프로시저안에서 프로시저1, 프로시저2, 프로시저3이 있고, 각 프로시저마다 스택에 변수를 넣는다면, 스택에는 프로시저1의 공간, 프로시저 2의 공간. 프로시저3의 공간으로 나눠지며, 각각을 스택 프레임이라고 할 수 있습니다. 스택은 상위주소에서 하위주소로 저장을 합니다.

 

EBP는 Enhance Base Pointer로 각 스택 프레임의 첫 시작 포인터를 의미합니다. 스택프레임은 EBP가 저장된 주소를 기준으로 나뉘어지며, 항상 함수를 시작할때는 이전의 EBP값을 저장시켜주어야합니다. main 프로시저안에 프로시저1, 프로시저 2, 프로시저3 이있고, 스택에 모두 저장되어있는 상태라고 한다면 아래와 같이 있어야합니다.

복귀 주소의 경우 call 명령어를 사용하면 자동으로 다음 주소가 스택에 push 됩니다. 이제 실제로 어셈블리어 코드로 어떻게 구현이 되고, 스택을 이용한 매개변수 전달 및 사용에대해서 알아보겠습니다.

 

- MySub 프로시저 예제

지금까지 eax 레지스터나 ebx 레지스터를 이용하여 매개변수를 전달하는 방법을 사용해왔습니다. 이제는 stack을 사용하여 프로그래밍을 해볼겁니다. 아래는 예제프로그램의 실행 순서입니다.

1. x, y 두개 변수를 입력받아 저장합니다.

2. x, y 두개의 변수를 스택에 푸쉬하고 Mysub 프로시저를 호출합니다.

3. sub 프로시저는 x-y의 값을 eax에 저장하고 return 합니다.

4. eax의 값을 출력합니다.

아래는 코드입니다.

 


;-----------------INCLUDE-------------------------
;
include 	c:\assembly\irvine32.inc
includelib  c:\assembly\irvine32.lib
includelib  c:\assembly\kernel32.lib
includelib  c:\assembly\user32.lib
;-----------------------------------------------


.data
Xstring BYTE "Enter the integer of X : ", null
Ystring BYTE "Enter the integer of Y : ", null
x DWORD 0
y DWORD 0

.code
main PROC

    mov edx, OFFSET Xstring
    call WriteString
    call ReadDec
    mov x, eax
    mov edx, OFFSET Ystring
    call WriteString
    call ReadDec
    mov y, eax
    push x
    push y
    call Mysub 
    call DumpRegs
    call WriteDec

    exit
    
main ENDP

;--------------------------------------------------------------------------
Mysub PROC
;
;Subtract x and y.
;Receive : x, y
;return : eax = x - y
;--------------------------------------------------------------------------
    push ebp
    mov ebp, esp
    mov eax, [ebp+12]
    mov ebx, [ebp+8]
    sub eax, ebx
    pop ebp
    ret 8

Mysub ENDP

END main

위 코드에서 주목할 점은 ebp+12 와 ebp+8부분과 ret 8 부분입니다. 일단, Mysub 프로시저가 호출되고 push ebp 까지 실행된 후의 스택을 보도록 하겠습니다.

위 사진과 스택의 구조가 같아서 x의 값은 EBP+12이고, Y의 값은 EBP+8입니다. 스택은 항상 32비트값을 집어 넣어야되며 만약 32비트값을 집어넣지않는다면 에러가 발생합니다. 또한, 메모리의 크기는 1바이트이기때문에 항상 32비트 값을 넣으면 주소는 4씩 커지게됩니다. 항상 PROC 마지막에는 pop ebp를 해준다음 ret을 해야 main 스택 프레임의 EBP값이 pop되고 return address가 스택의 맨 처음에 위치하게되어 ret 명령어가 작동됩니다.

 

ret 8의 경우는 매개변수의 처리를 위한 코드로 ret 이후 스택에 남은 x와 y를 처리하기위해 esp에 8을 빼도록 하는 겁니다. 이러한 방법을 STDCALL 규약이라고하며, 함수를 호출당한 쪽에서 처리를 하는 방법입니다. 만약 매개변수가 3개면 ret 12 4개면 16을 써줘야합니다. ret 8이후 stack의 구조는 아래와 같을 겁니다.

 

코드를 실행하면 아래와 같이 잘 실행됩니다.

 

Comments