외로운 Nova의 작업실
Assembly 언어 공부 - 21(Runtime Stack의 사용) 본문
안녕하세요, 이번 시간에는 Runtime Stack(실행시간 스택)을 사용하는 방법에대해서 알아보겠습니다.
- Runtime Stack
Runtime Stack은 스택 포인터 레지스터라고 하는 ESP 레지스터를 이용하여 CPU가 직접 관리하는 메모리 배열입니다. ESP 레지스터에는 스택에 있는 어떤 위치에 대한 32비트 오프셋을 저장합니다. ESP를 직접 조작하는 일은 거의 없으며, CALL, RET, PUSH, POP 과같은 명령어를 사용하여 간접적으로 수정됩니다.
- Runtime Stack의 구조
자료구조를 배우셨다면 잘 알듯이 LIFO 구조를 가지고 있습니다. 마지막에 넣은걸 먼저 빼내야 처음에 넣었던 것을 뺄 수가 있죠. 다만, 시스템적으로보자면 Runtime Stack은 큰 숫자의 주소를 먼저 사용하고 낮은 숫자의 주소를 나중에 사용합니다.
- PUSH
PUSH 명령어는 먼저 ESP를 감소시키고 다음에 소스 피연산자를 스택에 복사합니다. 피연산자가 16비트면 2씩, 32비트이면 4씩 감소시킵니다. 다만, 32비트 모드에서는 항상 32비트 피연산자를 주어야합니다.
- POP
POP 명령어는 먼저 ESP가 가리키는 스택의 원소의 내용을 피연산자로 복사한 다음에 ESP를 증가시킵니다.
- PUSHFD 와 POPFD
PUSHFD 명령어는 EFLAGS(모든 플래그) 레지스터를 스택에 푸쉬하고 POPFD 명령어는 스택을 EFLAGS 로 팝합니다. 프로그램을 실행할때 나중에 플래그를 이전 값으로 복원할 수 있도록 플래그를 스택에 백업해놓았다가 나중에 pop하여 다시 복원할 수 있습니다. 종종 한 블록의 코드를 PUSHFD 와 POPFD 사이에 넣습니다.
- PUSHAD, POPAD 와 PUSHA, POPA
PUSHAD 명령어는 32비트 범용 레지스터를 EAX, ECX, EDX, EBX, ESP(명령어 실행 이전 값),ㅡ EBP, ESI, EDI 의 순으로 스택에 푸쉬합니다. POPAD 명령어는 같은 레지스터들을 반대 순서로 스택에서 팝합니다. PUSHA 명령어는 16비트 범용 레지스터들 AX, CX, DX, BX, S{, BP, SI, DI 순으로 스택에 푸쉬합니다. POPA 명령어는 같은 레지스터들을 반대 순서로 팝합니다. 프로그램을 실행할때 모든 레지스터의 값들을 스택에 백업해놓았다가 나중에 pop하여 다시 복원할 수 있습니다. 종종 한 블록의 코드를 PUSHAD와 POPAD 사이에 넣곤합니다. 단, POPAD를 하게되면 이전에 레지스터의 값들은 덮어씌워져서 사라집니다.
- Stack 예제 프로그램
Stack을 사용하여 기존에 있는 문자열을 거꾸로 저장해보도록 하겠습니다.
include c:\assembly\irvine32.inc
includelib c:\assembly\irvine32.lib
includelib c:\assembly\kernel32.lib
includelib c:\assembly\user32.lib
.data
string BYTE "hello nova world", 0
lenString = ($ - string) - 1
.code
main PROC
mov esi, 0
mov ecx, lenString
L1: movzx eax, string[esi]
push eax
inc esi
Loop L1
mov esi, 0
mov ecx, lenString
L2: pop eax
mov string[esi], al
inc esi
Loop L2
mov edx, OFFSET string
call WriteString
call Crlf
exit
main ENDP
END main
위 코드에서 주의해야할 점은 문자하나하나는 BYTE 크기 이기때문에 movzx 명령어를 사용하여 EAX에 32비트로 저장하고 32비트로 push 해줘야하는 것입니다. 또한 pop할때도 32비트로 나오기때문에 실질적인 문자가 저장된 al부분만 string 배열에 저장하는 부분도 주의해야합니다. 위 코드를 실행시켜보겠습니다.
문자열이 역순으로 배열 되는 것을 확인할 수 있습니다.
'Programming > Assembly' 카테고리의 다른 글
Assembly 언어 공부 - 22(점프 명령어 이론) (0) | 2022.08.25 |
---|---|
Assembly 언어 공부 - 22(프로시저의 사용) (0) | 2022.08.24 |
Assembly 언어 공부 - 20(라이브러리 예제 프로그램) (0) | 2022.08.23 |
Assembly 언어 공부 - 19(라이브러리 프로시저 설명) (0) | 2022.08.18 |
Assembly 언어 공부 - 18(JMP와 LOOP 명령어 이론 및 실습) (0) | 2022.08.02 |