Argument Passing

Setup the argument for user program in process_exec()

<aside> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" width="40px" /> process_exec() 함수에 있는 “유저 프로그램”을 위한 인자를 세팅해봅시다.

</aside>

x86-64 Calling Convention (x86-64 시스템에서의 호출 규약)

This section summarizes important points of the convention used for normal function calls on 64-bit x86-64 implementations of Unix. Some details are omitted for brevity. For more detail, you can refer System V AMD64 ABI.

<aside> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" width="40px" /> 이번 절에서는, 유닉스의 64비트 x86-64 구현들에 있는- 일반적인 함수호출 규약의 중요한 포인트들을 요약해보도록 하겠습니다.

몇몇 디테일은 간결성을 위해 생략되었습니다. 디테일한 정보를 원한다면, System V AMD64 ABI를 참고하세요.

</aside>

The calling convention works like this:

  1. User-level applications use as integer registers for passing the sequence %rdi%rsi%rdx%rcx%r8 and %r9.
  2. The caller pushes the address of its next instruction (the return address) on the stack and jumps to the first instruction of the callee. A single x86-64 instruction, CALL, does both.
  3. The callee executes.
  4. If the callee has a return value, it stores it into register RAX.
  5. The callee returns by popping the return address from the stack and jumping to the location it specifies, using the x86-64 RET instruction.

<aside> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" width="40px" /> 호출 규약은 다음과 같습니다 :

  1. 유저-레벨 어플리케이션은 %rdi%rsi%rdx%rcx%r8%r9 시퀀스들을 전달하기 위해 정수 레지스터를 사용합니다.
  2. 호출자는 다음 인스트럭션의 주소(리턴 어드레스)를 스택에 푸시하고, 피호출자의 첫번째 인스트럭션으로 점프합니다. CALL 이라는 x86-64 인스트럭션 하나가 이 두 가지를 모두 수행합니다.
  3. 피호출자가 실행됩니다.
  4. 만약 피호출자가 리턴 값을 가지고 있다면, 리턴 값은 레지스터 RAX에 저장됩니다.
  5. 피호출자는 x86-64 인스트럭션인 RET *(리턴)*를 사용해서, 스택에 받았던 리턴 어드레스를 pop하고 그 주소가 가리키는 곳으로 점프함으로써 리턴됩니다. </aside>

Consider a function f() that takes three int arguments. This diagram shows a sample stack frame and register state as seen by the callee at the beginning of step 3 above, supposing that f() is invoked as f(1, 2, 3). The initial stack address is arbitrary:

<aside> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" width="40px" /> 세 개의 정수 인자를 받는 함수 f() 가 있다고 생각해봅시다.

아래 도식은 위의 3번 항목에 있는 피호출자가 실행되는 시점에, 스택 프레임과 레지스터 상태가 어떤 식으로 되어있는지에 대한 예시를 보여줍니다. f()f(1, 2, 3)으로 호출되었다고 가정합시다.

초기화된 스택의 주소는 임의의 숫자로 치면 다음과 같습니다 :

</aside>

                             +----------------+
stack pointer --> 0x4747fe70 | return address |
                             +----------------+
RDI: 0x0000000000000001 | RSI: 0x0000000000000002 | RDX: 0x0000000000000003

Program Startup Details (프로그램 시작과 관련된 디테일들)

The Pintos C library for user programs designates _start(), in lib/user/entry.c, as the entry point for user programs. This function is a wrapper around main() that calls exit() if main() returns:

<aside> <img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" alt="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/99abd4a7-3021-4fa1-9e83-eef264b263a4/angry_mjh.png" width="40px" /> 유저 프로그램을 위한 Pintos C 라이브러리는 _start() 함수를 유저 프로그램의 시작 포인트로 지정합니다. _start()lib/user/entry.c 에 있습니다.

여기서 _start()main() 함수를 감싸고 있는 함수입니다. main() 은 리턴되면서 exit()을 호출하게 됩니다.

</aside>