여기서 부터는 기말고사 부분에 해당한다.
사실 앞에 부분이 정확하게 기억은 나지 않지만 강의를 듣다보니 아 ! 이랬구나 하는 부분들이 신기했다,,,
뭐 하튼! 시작.
독립된 기능들을 말할떈 funciton 이라 한다.
그리고 이 function 들의 합으로 이루어진 전체의 합을 Precedure 라 한다.
-> Return 값이 없어도된다.( 있을때는 여러개 있어도 된다)
하지만 Function 은 return 값이 있어야한다.(하나)
Calling Convention 의 정의는 함수 호출에 대한 약속이다.
이러한 약속은 Precedure Call 이라 많이 불린다.
명령어는 순서대로 진행된다. 하지만 Function 은 중구난방으로 이루어져있다.
그래서 PC 값을 통하여 순서에 맞게 수행되어야함.
Caller 는 호출하는놈
Callee 는 호출되는놈이다.
Caller 는 Callee 에게 인자를 담아서 전달한다.
그리고 미리정의된 위치에다가 결과값을 저장한다.
위 그림에서 만약 Main에 20개의 변수, f1 에도 20개의 변수가 있다 가정한다. 근데 register는 32개인데 어떻게 하나?
--> 더 많은 Memory Space 가 필요하게 된다.
Jump 명령어는 J 로 쓰며 Procedures 가 Single Times 호출 되었을떄 사용되어 진다.
Jump and Link 명령어는 jal 로 쓰며 Procedures 가 Multiple Times 호출 되었을때 사용되어 진다.
JAL 은 다음 명령어가 종료되는 위치의 Memory 주소(PC+4)를 X1 레지스터에 저장한다.
하지만 Jump and Link 는 x1에 overwrite 될 문제가 있다.
그래서 레지스터 값들을 save 하고 restore 할 방법을 찾아야함.
Stack 은 자료구조를 배웠다면 알수있는 자료구조 중 하나이다.
Dynamic data 를 할당하기 위한 구조라 한다.
Stack Frame 을 포함하고 있고, 잘 알다시피 LIFO 방식으로 관리된다.
Stack 이 저장하는것들에는 Return Adress,Local Variable , Argument Value,Argument Build 가 있는데 그러한 부분은 뒷장에서 더 깊게 배운다고 한다.
그리고 스택에는 SP(Stack Pointer) 이라 하는 스택의 Top(가장 최근에 들어온 값) 을 찾아주는 레지스터를 가지고 있다. X2 라 한다.
Push , Pop 에 따라 Sp가 값이 바뀌게 되는데
Push 를 하게 되면 SP의 값을 Down 하고 , Store 한다.
그리고 Pop 을 하게 되면 Sp 의 값을 Up 하고 Load 한다.
Push하면 Sp 를 Down 하고 Store 한다고 알고 있었는데, 왜 8이라는 값을 뺴주는지 궁금했다. 그냥 간단하게 그린그림처럼 밑이 낮은주소라 생각하면된다.
나는 밑으로 갈수록 높은 주소라 생각해서 그렇게 생각한듯하다.
그래서 Push 를 하게 되면 1개의 값을 넣어줄만큼의 크기만큼 SP 값을 내려주고 그 부분에 값을 넣어주면 된다.
여기 예시에서는 레지스터 T5의 값을 0(SP)의 메모리 위치에 SD(Store Double) 해주었다.
SP 는 가장 최근에 들어온 값의 메모리 주소를 나타낸다 했다.
그래서 Pop 을 하게 되면 가장 최근 위치인 0(SP) 에서 해당 레지스터로 값을 LD(Load Double) 하고 다시 SP 의 위치를 그 크기 만큼 높여주면 되는 것이다.
Procdeure Call Instrcutions 에는 Procedure Call 과 Procedure return 이 있다.
Procedure call 은 ra(return address) 에 다음 instruction 의 주소를 넣고 실행한다.
Procedure return 은 Jal 과 비슷하지만 0+ ra의 주소 를 더한 주소로 Jump 를 한다.
근데 만약 Recuresive call 일떄는 return address 가 자꾸 바뀌게 된다. 그래서 return address 를 관리하는 call stack 이 필요하게 된다.
Callee 는 자기만의 register 를 가지고 있어야 한다.
Caller 가 callee 에게 최대 8개의 register들은 제공을 한다.
callee 의 인자들은 register x10 ~ x17(a0 ~ a7) 에 전달된다.
그리고 x10 ~ x17 의 원래 값은 Caller 의 stack Frame 에 저장되어야 한다. 다시 사용될수 있기 떄문에
그리고 만약 8개 이상의 인자들이 필요하게 된다면 8개까진 Register 에 9개부터는 Stack 에 저장되게 된다.
그리고 반환값 (Return value) 는 x10,x11 ( a0,a1)에 저장되게 된다.
이 그림을 보고 그냥 따라가면 된다.
SP 는 다음 스택을 쌓아야 하는 위치주소를 가지고있고
FP 는 현재 함수가 끝난뒤에 반환될 위치 주소를 가지고 있다.
Leaf Procedure는 또 다른 Procedure 를 호출하지 않는 Procedure 이다.
leaf 함수의 인자 g,h,i,j 가 각각 x10~x13 에 저장 될꺼고, 나는 4,3,2,1 의 값을 넣어주고 간단한 그림을 그렸다.
먼저 3개의 Temp Register 를 위해 3개의 크기만큼 SP를 빼줘야한다.
그리고 각 x5,x6,x20 의 원본값을 stack에 넣어준다.
그리고 실제 x5의 값에 g,h 를 더한 7의 값
그리고 x6에는 i,j를 더한 3의 값이 들어가게 되고
x20 에는 x5와 x6을 뺸 4의 값이 들어가게된다.
그리고 반환값으로 x10 or x11 에 저장해준다했다.
여기선 x10에다가 반환값인 x20을 저장해줬다.
그리고 원래 x20,x6,x5 의 값에는 원래의 값이 들어가야한다.
그리고 다시 스택의 크기를 원래대로 줄여준 24를 더해서 return 을 하게 된다.
Leaf Procedure 가 또 다른 procedure를 호출하지 않는다면 Non-leaf 는 당연하게도 또 다른 Procedure를 호출하는 Procedure 일것이다.
Non-Leaf 부분은 N의 값을 다르게 넣어서 실제로 과정을 따라가는것이 이 글을 보는것 보다 더 도움 될것,
스택은 stack Frame을 포함한다 했다.
1 Stack Frame per 1 dynamic function 이라 할수 있다.
함수의 생존 기간동안만 존재하게 된다.
Data 는 무조건 Malloc() 으로부터 Free()를 해야 삭제가된다.
Free() 를 하지 않으면 Dangling pointer problem 을 가진다고 한다.