지난 주에 해결 안되었던 문제를 동료의 질문과 조교님의 답변, 그리고 참고한 책으로 해결할 수 있었다.
래 문제 상황을 정리하기 위해 개념을 다시 간단하게 정리하고 넘어가야 한다
관련해서 https://www.youtube.com/watch?v=Q9DHaqlS3ZM&list=PLyboo2CCDSWnhzzzzDQ3OBPrRiIjl-aIE&index=7 와 컴퓨터 시스템 책 정리한 글, 비공개 / 참고 책, [컴퓨터 시스템]
스택은 push, pop으로 이루어진다.
push 연산은 rsp 값을 먼저 이동시킨다는 것이 가졌던 의문 해결의 단서가 되었다.
x86-64에서 스택 포인터를 8 바이트 먼저 감소시키고, 그 값을 스택의 새로운 탑(top)에 기록하는 것이 push 인스트럭션이다.
subq &8, %rsp // 스택 포인터 8 바이트 먼저 감소시키기
movq %rbp, (%rsp) // rbp를 스택에 저장
if(USER_STACK - (uint64_t)addr <= ONE_MB)

여기까진 잘 이해가 갔지만 문제가 발생했다. 처음에는 해당 부분을 확인하고 페이지를 한 페이지만 할당해줬다.
당연히 rsp 보다 -8 한 것만큼 아래이므로 한 페이지면 될 것 같다는 생각에서였다. 그런데 테스트는 실패했고 실제 주소를 찍어보니

이렇게 실제 rsp가 마지막으로 사용되었을 것이라 추정되는 페이지 (첫 페이지) 보다 한 참 아래에 f->rsp가 있었고, 그것에 -8한 주소를 요청해 page falut가 나는 것이었다.
페이지가 없는데 어떻게 rsp가 저기로 이동하는지, page도 없는데 거기서 어떤 작업을 했길래 rsp-8로 추가적인 코드 실행이 있었는지 이해가 가지 않았다'
rsp-8로 한 칸 한 칸씩 stack push 하고 pop 하는줄 알았기 때문이다.
조교님 답변을 우선 보면,
rsp는 push/pop instruction에 의해 +-8 bytes씩 이동하는것 이외에도 arithmetic instruction과 indirect memory reference instruction의 인자로 사용될 수 있습니다.
실제로 디버깅 해봤을 때 test_main()에서 배열을 선언하고 arc4를 선언한 곳까지 에서는 페이지 폴트가 나지 않았다. push 연산이 일어나고 이 때문에 rsp - 8 이 발생하며, 이는 push 연산이라 단순히 rsp 를 이동해 준 것과 달리 페이지 폴트가 발생한다. 좀 더 세밀하게 디버깅 해보니 return address 를 저장하기 위해서 push 연산이 일어나는 것이 아니었다. test_main()에서 명시되어있지 않지만 pintOS의 테스트는 실행시 아래와 같이 결과가 출력되는데
이를 위한 write 요청이 일어나 페이지 폴트가 발생하는 것이어었다.
%rbp에 쓰임에 대해서 알게 되었다. %rsp 값이 이리저리 바뀌게 된다.frame pointer로 사용한다. 함수가 호출되기 직적에 스택포인터의 복사본을 저장한다. 

이렇게 rbp를 먼저 push 하고 rsp를 저장한다. 