이 부분은 리눅스 기반 64비트(x86-64) 환경에서 함수 호출 규약을 요약한 것. 간단하게 설명하기 위해 일부 세부 사항은 생략되었음. 더 자세한 내용은 System V AMD64 ABI 문서를 참고
호출 규약은 다음과 같이 동작 :
사용자 수준 애플리케이션은 인자를 레지스터 순서대로 전달 :
%rdi, %rsi, %rdx, %rcx, %r8, %r9
호출자(caller)는 **자신의 다음 명령어 주소(리턴 주소)**를 스택에 푸시한 뒤, 피호출자(callee)의 첫 번째 명령어로 점프 :
CALL 명령어가 이 두 동작을 동시에 수행
피호출자(callee)가 실행됨
만약 피호출자가 반환 값을 가지면, 그것은 RAX 레지스터에 저장
피호출자는 스택에서 반환 주소를 꺼내서, RET 명령어로 해당 위치로 점프하며 복귀
int 인자 3개를 받는 함수 f()가 있는 상황 가정
호출 시점: f(1, 2, 3)
이때 피호출자 입장에서의 레지스터와 스택 상태는 다음과 같음 :
스택 포인터 → 0x4747fe70 | return address |
+----------------+
RDI: 0x0000000000000001
RSI: 0x0000000000000002
RDX: 0x0000000000000003
Pintos의 사용자 프로그램 라이브러리(lib/user/entry.c)는 _start() 함수를 **프로그램 진입점(entry point)**으로 지정
_start()는 main()을 호출하고, 만약 main()이 반환되면 자동으로 exit()를 호출 :
void
_start (int argc, char *argv[]) {
exit (main (argc, argv));
}
즉, 커널은 사용자 프로그램이 시작되기 전에 레지스터에 인자를 적절히 세팅 필요. 이 인자 전달 규칙은 일반적인 함수 호출 규약과 동일하게 적용
/bin/ls -l foo bar처리 과정
/bin/ls, -l, foo, bar