인자 뿐만 아니라 내부에서 사용하는 변수를 저장하는 용도로도 사용한다.
파일 실행 -> 램에 올라감
메모리 저장구조
컴파일 시 크기가 결정
CODE : 함수, 제어문, 상수 영역
DATA : 전역 변수
BSS : 전역 변수
Run time 시 크기가 결정
HEAP : 동적 할당
STACK : 지역 변수
스택 프레임
높은 주소부터 사용한다.
지역 변수, 반환 주소값, 매개변수를 저장한다.
레지스터는 다양한 용도로 사용
; rsp : 0x60fe38
; push는 8바이트 단위
push 1 ; rsp : 0x60fe30, 0x60fe30 -> {0x1, 0x0, 0x0, ...}
push 2 ; rsp : 0x60fe28, {0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
push 3 ; rsp : 0x60fe20, {0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
pop rax
pop rbx
pop rcx ; rsp : 0x60fe38
MAX함수를 다시 만들어보자.
MAX함수 호출 시,
Stack Memory에는 매개변수 1, 2, 돌아가서 실행할 주소값(rip를 이용), 이전 BP값, 내부 변수를 저장한다.
BP를 SP로 세팅하는 이유는 스택 메모리에 수월하게 접근하기 위해서인데, SP는 동적으로 움직일 수 있기 때문에 SP를 이용하여 상대 주소를 계산하면, 코드가 어려워진다는 문제가 있다. 그래서 BP에 현재 SP를 고정해두고 상대 주소를 계산하여 스택 메모리에 접근하는 개념이다. 함수 진입 시 상위 호출의 BP를 스택에 저장해두고, 함수 반환 전 스택에서 상위 호출의 BP를 복원한다.
BP는 SP를 고정시켜서 스택의 상대 주소를 계산하는 데 쓰인다.
push rax
push rbx
push 1 ; 매개 변수
push 2 ; 매개 변수
call MAX
PRINT_DEC 8, rax
NEWLINE
add rsp, 16 ; push 1, push 2 복원
pop rbx
pop rax
MAX:
push rbp ; 이전 BP값 스택에 저장
mov rbp, rsp ; rsp를 rbp에 저장
mov rax, [rbp+16]
mov rbx, [rbp+24]
cmp rax, rbx
jg L1
mov rax, rbx ; 여기서는 반환값을 rax에 담는다.
L1:
pop rbp ; 스택에 저장되어 있는 이전 BP값을 다시 rbp로
ret
위 코드에서 add rsp, 16 명령을 실행하는 이유는 push 1, push 2로 인해 16바이트만큼 감소한 sp값을 되돌려 주기 위함이며, 그렇지 않으면 메인 함수에서 반환할 때 돌아갈 주소 값을 잘못 읽게 되므로 프로그램이 크래시가 난다.
push rax
push rbx
...
pop rbx
pop rax
는 rax, rbx 레지스터가 MAX 함수 호출 전에 유용하게 쓰이고 있는 경우, 값을 스택에 저장했다가 복원하는 코드이다.