Chapter 8 가상머신 I: 프로그램 제어 - [밑바닥부터 만드는 컴퓨팅 시스템]

SeungHeon Kim·2022년 5월 12일
0

7장에서 만든 VM에 이어서 중첩 서브루틴을 처리하는데 쓰이는 '스택 기반 구조'를 설계하고 구현할 것이다.

8.1 배경

위와 같이 고수준 언어를 사용하면 얻을 수 있는 고수준 언어의 표현력이 있다.

  1. sqrt나 power 같은 고급 연산을 필요에 따라 자유롭게 정의할 수 있다.
  2. 정의도니 서브루틴을 마치 +와 * 같은 기본 연산처럼 자유롭게 호출할 수 있다.
  3. 호출된 서브루틴이 실행되고 나면, 자동으로 코드 내의 다음 명령을 반환한다.

이렇게 자유로운 표현이 가능해지면, 우리는 알고리즘의 세계에 한층 더 가까운 추상적인 코드를 작성할 수 있다. 물론 추상화 수준이 높아질수록 저수준에서 해야 할 작업은 더 늘어난다. 우리가 편하게 고수준에서 프로그래밍을 하면 뒷단에서는 다음과 같은 일들이 일어난다.

위의 그림은 Main 함수에서 Sub Routine을 호출하기 전 상황을 그리고 있다.
call 명령을 만나면, 스택에는 Sub Routine으로 넘겨줄 인자 값과, 다시 돌아올 주소 값, Main에서 사용하던 각종 세그먼트 정보(주소) 그리고 Sub Routine에서 사용할 지역 변수공간이 저장된다.
Sub Routine에서의 작업이 모두 끝나면 Main으로 넘길 리턴 값을 스택에 push한다.
다시 Main 함수로 돌아가기 전에 스택에 저장했던 Main에서 사용하던 세그먼트 정보를 다시 불러오고 돌아갈 리턴 주소를 설정한다. 그리고 스택에 남은 인자 값, 지역 변수 공간은 이제 무시하고 그들이 있던 위치를 리턴 값이 대신한다.
마지막으로 설정된 리턴 주소로 점프하는 것으로 call Sub Routine 연산이 끝난다.

8.2 VM 명세 2부

8.2.1 프로그램 흐름 제어 명령

이 VM 언어에는 세 가지 프로그램 흐름 제어 명령이 있다.

  • label LABEL
    - 현재 함수 코드 위치에 레이블을 붙인다. 그 위치로만 점프가 가능하다.
  • goto LABEL
    - 무조건 분기 명령으로, LABEL 위치부터 실행하라는 명령이다.
  • if-goto LABEL
    - 스택의 최상단 값을 꺼내서 그 값이 0이 아니면 LABEL 위치에서 실행을 계속하고, 0이면 프로그램 다음 명령을 실행한다.

8.2.2 함수 호출 명령

  • function F n
    - 이름이 F고 지역 변수가 n개인 함수 코드가 시작된다.
  • call F m
    - 함수 F를 호출한다. 이때 스택에 m개의 인수가 push되었다는 정보도 같이 전달한다.
  • return
    - 호출한 함수의 다음 위치로 점프한다.

8.2.3 함수 호출 규약

  • 호출하는 함수 관점:

    • 함수를 호출하기 전에 호출자는 필요한 수의 인수를 스택에 푸시해야 한다.
    • 다음으로 호출자는 call 명령으로 함수를 불러온다.
    • 호출된 함수가 바노한된 후에는, 호출자가 호출하기 전에 푸시한 인수들은 스택에서 사라지고 반환 값이 스택 최상단에 있게 된다.
    • 호출된 함수가 반환된 후에, 호출자의 메모리 세그먼트들은 호출 전과 동일하며, temp 세그먼트는 미정의 상태다.
  • 호출되는 함수 관점:

    • 호출된 함수가 실행을 시작할 때, argument 세그먼트는 호출자가 넘겨준 실제 인수 값으로 초기화되며, local 변수 세그먼트는 할당되고 0으로 초기화된다. 호출된 함수가 바라보는 static 세그먼트는 그 함수가 속하는 VM 파일의 static 세그먼트로 설정되며, 작업 스택은 비어있다. this, that, pointer, temp 세그먼트들은 시작 전에는 미정의 상태다.
    • 반환되기 전에, 호출된 함수는 값을 하나 스택에 푸시해야 한다.

8.3 구현

0개의 댓글