본문 바로가기

Assembly

5-1강 - Procedure 1 (Stack Operation)

cf> 메모리를 그릴 때

1> 보통

위 = 낮은 주소 (00000000)

아래 = 높은 주소 (FFFFFFFF)

로 그린다.

 

2> stack

하지만 stack은 decrement의 느낌을 주기 위해 반대로 그림을 그린다.

 

1. Stack Operations

1) Runtime Stack

1> stack

- LIFO (Last In First Out)

- 한 쪽 끝(top)에서만 삽입과 삭제가 일어나는 구조

(Stack을 그릴 때는 평소(위 = 낮은 주소, 아래 높은 주소)와 반대로 그린다.)

2> Stack Pointer 

- stack을 가리키는 pointer (TOP)

- stack frame에서 stack의 가장 마지막 주소가 저장된다.

- SS register가 가리키는 stack segment의 맨 꼭대기를 가리키는 pointer

- 32-bit에서는 ESP, real-address(16-bit) 구조에서는 SP

 

3> Stack Segment (SS register)

 

cf> 32-bit 체제에서는 메모리 한 칸 이동할 때마다 4씩 차이가 난다.

 

2) PUSH

1> 과정

- SP(stack pointer)가 4byte(stack element size in 32-bit)만큼 decrement

- SP가 가리키는 곳에 값을 저장

2> 특징

- stack은 아래 방향으로 증가한다.

- SP 아래로는 사용할 수 있는 메모리이다. (overflow가 일어나지 않는 한)

3) POP

1> 과정

- SP가 가리키는 값을 다른 register나 variable로 copy

- (복사한 후) SP에 4byte(stack element size in 32-bit) or 2byte만큼 increment-> SP가 가리키는 값을 제거

- SP가 4byte(stack element size in 32-bit)만큼 increment

 

4) stack 구조 예시

1> PUSH와 POP 예시

push esi                   ; push registers
push ecx
push ebx

mov esi, OFFSET dwordVal   ; display some memory
mov ecx, LENGTHOF dwordVal
mov ebx, TYPE dwordVal
call DumpMem

pop ebx                    ; restore registers
pop ecx
pop esi

- push와 pop은 반대의 순서로 일어난다.

- call DumpMem : esi, ecx, ebx가 DumpMem의 parameter로 넘어간다. (register로 parameter passing 한다.)

- 원래는 DumpMem도 loop를 돌면서 3번 출력을 하기 때문에 ECI가 필요하다. 

=> register의 값을 임시적으로 저장히기 위해 push

=> DumpMem이 끝나고 나서 pop

 

 

2> Nested Loop

    mov ecx, 100    ; set outer loop count
L1:                 ; begin the outer loop
    push ecx        ; save outer loop count
; ### INNER LOOP START ###
    mov ecx, 20     ; set inner loop count
L2:                 ; begin the inner loop
    ;
    ;
    loop L2         ; repeat the inner loop
; ### INNER LOOP END ###
    pop ecx         ; restore outer loop count
    loop L1         ; repeat the outer loop

- loop를 중첩하니 ECX가 혼란이 생길 수 있다. 

- 그래서 outer loop에서 ECX를 임시 저장하기 위해 push를 사용한다.

- (line 3) push ecx : 첫 번째 loop의 counter를 잠시 stack에 저장

- (line 5) mov ecx, 20 : 두 번째 loop의 counter를 (20으로) 할당 받는다.

- (line 11) pop ecx : 첫 번째 loop의 counter를 다시 받는다.

 

3> Reversing a String

- 기본 원리 : 각 글자(character)를 stack에 push

.data
aName BYTE “I like StarII",0
nameSize = ($ - aName) - 1		; nameSize = 12

.code
	mov ecx,nameSize
	mov esi,0
L1: movzx eax,aName[esi] 		; get character
	push eax 			; push on stack
	inc esi
	Loop L1
    
	mov ecx,nameSize
	mov esi,0
L2: pop eax ; get character
	mov aName[esi],al 		; store in string
	inc esi
	Loop L2

 

cf> Related Instruction

1> PUSHFD, POPFD : EFLAG register들 push & pop

2> PUSHAD, POPAD 

PUSHAD : 32-bit general-purpose register들을 stack에 push

(order : EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI)

POPAD : 32-bit general-purpose register들을 stack에 pop in reverse order 

3> PUSHA, POPA : 16-bit general-purpose register들을 stack에 push & pop