Skip to content

Commit

Permalink
Chapter08 정리
Browse files Browse the repository at this point in the history
  • Loading branch information
jkde7721 authored Feb 14, 2023
1 parent 555c290 commit ea27937
Showing 1 changed file with 227 additions and 0 deletions.
227 changes: 227 additions & 0 deletions 08/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Ch08 가상 머신 II: 프로그램 제어

### 고수준 언어의 세 가지 특성

1. 고급 연산을 필요에 따라 자유롭게 정의 가능
2. 서브루틴을 기본 연산처럼 자유롭게 사용(호출) 가능
3. 호출된 서브루틴이 실행되고 나면 그 종료 제어가 코드 내의 다음 명령으로 반환

<br>

### 서브루틴 호출 시, 필요한 처리

1. 호출자에서 호출된 서브루틴으로 **매개변수 전달**
2. 호출된 서브루틴을 시행하기 전에 **호출자 상태 저장**
3. 호출된 서브루틴의 **지역 변수에 공간 할당**
4. 호출된 서브루틴을 실행하기 위해 **점프**
5. 호출된 서브루틴의 **결과값을 호출자로 반환**
6. 값이 반환될 때, 호출된 서브루틴이 점유한 메모리 공간 재활용
7. **호출자 상태 복구**
8. 호출자 코드에서 이전에 점프했던 지점 바로 다음 코드를 실행하기 위해 **점프**

<br>

## 8.1.1 프로그램 흐름 제어

컴퓨터 프로그램은 한 명령어씩 순차적으로 실행하는 방식이 기본

- **goto destination** : 프로그램 내 특정 위치부터 실행 지속

*위치 설정 방식 : 다음에 실행될 명령어의 물리적 주소 지정하는 방식

(코드 내 특정 지점을 뜻하는 **기호 레이블**을 통해 점프할 위치 지정)

- **if-goto destination** : 불 조건문이 참일 경우만 점프, 거짓이면 원래 프로그램 흐름대로 바로 다음번 명령 실행

<br>

### 저수준 제어 흐름

```basic
// 제어 흐름 구조
if (cond)
s1
else
s2
// 의사 VM 코드
VM code for computing ~(cond)
if-goto L1
VM code for executing s2
goto L2
label L1
VM code for executing s1
label L2
```

```basic
// 제어 흐름 구조
while (cond)
s1
...
// 의사 VM 코드
label L1
VM code for computing ~(cond)
if-goto L2
goto L3
label L2
VM code for executing s1
goto L1
label L3
...
```

<br>

## 8.1.2 서브루틴 호출

- 고수준 연산 단위 = 서브루틴, 프로시저, 함수, 메서드
- 기초 명령(내장형 명령, add)과 고수준 연산(사용자 정의 서브루틴, power)은 같은 방식으로 **인수 처리**하고 **값 반환**

(차이점 : 서브루틴 앞에 **call** 키워드 쓰임)

- 호출 및 반환 논리의 단계적인 특성 : 서브루틴 호출이 아무리 많이 중첩되어 있더라도, 어느 한 시점에는 중첩된 서브루틴들 중 맨 위의 것만 실행, 그 아래 다른 서브루틴 호출들은 현재 실행되는 서브루틴이 종료되기를 기다림

- **프레임**(frame) : 서브루틴의 **지역 변수**, 서브루틴이 연산할 **인수**들, **작업 스택**과 연산을 지원하는 **메모리 세그먼트** 통칭
- **전역 스택**(global stack) : 현재 서브루틴과, 그 서브루틴의 반환을 대기하는 다른 모든 서브루틴들의 **프레임**을 담고 있는 메모리 영역 (현재 서브루틴의 작업 스택이 전역 스택의 맨 위에 위치)

<br>

### 저수준에서 call xxx 연산 구현

1. 호출자의 프레임을 스택에 저장
2. 호출된 서브루틴의 지역 변수에게 스택 공간 할당
3. 실행할 코드로 점프

(**call** 명령에 명시된 서브루틴의 메모리 주소를 확인하고 그 주소로 시작하는 실행 코드로 점프)

- 호출된 서브루틴에서 **return** 명령으로 반환할 때 → 반환될 주소 명령에 표시X

⇒ 현재 서브루틴을 호출한 call 명령이 프로그램 어디에 있든지 간에 그 다음 명령으로 점프해서 실행 (**다음 명령의 메모리 위치** = **반환 주소**)

<br>

## 8.2.1 프로그램 흐름 제어 명령 명세

- **label label** : 현재 함수 코드 위치에 레이블 붙임 (레이블이 정의된 함수 내부에서만 레이블 유효)
- **goto label** : 무조건 분기 명령, label 위치부터 실행 (점프할 위치는 같은 함수 내)
- **if-goto label** : 조건 분기 명령, 스택의 최상단 값을 꺼내서 그 값이 0이 아니면 label로 표시된 위치에서 계속 실행, 값이 0이면 프로그램 다음 명령 실행 (점프할 위치는 같은 함수 내)

<br>

## 8.2.2 함수 호출 명령 명세

함수 이름의 번위는 전역적 (모든 파일 내의 함수 이름들이 공유, 함수 이름으로 서로 호출)

- **function f n** : 이름이 f, 지역 변수가 n개인 함수 코드 시작
- **call f m** : 함수 f 호출 (호출자가 스택에 m개의 인수 푸시)
- **return** : 호출한 함수로 반환

<br>

## 8.2.3 함수 호출 규약

VM 함수의 실행이 시작될 때 **메모리 세그먼트**들과 **스택**들로 이루어진 개별 환경으로 둘러싸임

⇒ VM이 VM 함수마다 이러한 가상 환경을 만들어줌

### 호출하는 함수 관점

- 함수 호출 전 필요한 수의 **인수 스택에 푸시**
- **call** 명령으로 **함수 호출**
- 호출된 함수가 반환된 후, 호출하기 전 푸시한 인수들은 스택에서 사라지고 **반환값은 스택 최상단에 위치**
- 호출된 함수가 반환된 후, 호출자의 메모리 세그먼트들(argument, local, static, this, that, pointer)은 **호출 전과 동일**, temp 세그먼트는 미정의 상태

### 호출되는 함수 관점

- 호출된 함수가 실행을 시작할 때
- argument 세그먼트 : 호출자가 넘겨준 실제 인수값으로 초기화
- local 세그먼트 : 할당 후 0으로 초기화
- static 세그먼트 : 그 함수가 속하는 VM 파일의 static 세그먼트로 설정
- this, that, pointer, temp 세그먼트 : 시작 전에는 미정의 상태
- 작업 스택은 empty
- 반환되기 전 **값 하나 스택에 푸시**

<br>

## 8.2.4 초기화

- VM 프로그램 = VM 함수들의 모음
- VM이 실행될 때(또는 리셋될 때), 항상 **Sys.init** 이라는 인수 없는 VM 함수 먼저 실행!!
- **Sys.init** : 사용자 프로그램의 **메인 함수 호출**

<br>

## 8.3.1 핵 플랫폼에서 표준 VM 매핑, 2부

### 전역 스택

- 함수가 호출될 때마다 전역 스택에는 새로운 블록 추가
- 블록은 호출된 함수에서 사용하는 **인수**, **지역변수**, **빈 작업 스택**과 호출하는 함수의 상태를 저장하는 **포인터**로 구성

### 함수 호출 규약 구현

**call f n** : n개의 인수를 스택에 푸시한 후 함수 f 호출

```basic
push return-address // 아래 선언된 레이블 사용
push LCL // 호출한 함수의 LCL 저장
push ARG // 호출한 함수의 ARG 저장
push THIS // 호출한 함수의 THIS 저장
push THAT // 호출한 함수의 THAT 저장
ARG = SP-n-5 // ARG 위치 재설정 (n은 인수 개수, 5는 호출한 함수의 프레임 개수)
LCL = SP // LCL 위치 재설정
goto f // 제어 이동
(return-address) // return-address 레이블 선언
```

**function f k** : k개의 지역 변수가 있는 함수 f 선언

```basic
(f) // 함수 시작 레이블 선언
repeat k times: // k는 지역 변수 개수
PUSH 0 // 지역 변수 모두 0으로 초기화
```

**return** : 어떤 함수에서 반환

```basic
FRAME = LCL // FRANE은 임시 변수
RET = *(FRAME-5) // return-address 임시 변수에 저장
*ARG = pop() // 호출자 위해 반환값 위치 재설정(함수의 결과값 첫번째 인수 자리에 저장)
SP = ARG + 1 // 호출자의 SP 복구
THAT = *(FRAME-1) // 호출자의 THAT 복구
THIS = *(FRAME-2) // 호출자의 THIS 복구
ARG = *(FRAME-3) // 호출자의 ARG 복구
LCL = *(FRAME-4) // 호출자의 LCL 복구
goto RET // (호출자 코드 내) return-address로 점프
```

<br>

### 어셈블리 언어 기호들

|**기호**|**사용법**|
|--------|----------|
|**functionName$label**|VM 함수 f 내의 label b 명령마다 전역적으로 유일한 기호 **f$b** 생성 (goto b, if-goto b 명령 번역 시, b 대신 전체 레이블 f$b 사용)|
|**(FunctionName)**|VM 함수 f마다 명령어 메모리 내 시작 포인트를 가리키는 기호 **f** 생성|
|**return-address**|VM 함수마다 **반환 주소**, 즉 함수가 호출된 곳 바로 다음 명령의 메모리 주소를 가리키는 유일한 기호 생성|

<br>

### 부트스트랩 코드 : 컴퓨터가 부팅될 때 처음 실행되는 코드

- 번역된 .asm 파일이 준수해야 하는 규칙
- VM 스택은 RAM[**256**] 위치부터 매핑
- 실행되는 첫 번째 VM 함수는 **Sys.init**

### 핵 컴퓨터의 부트스트랩 코드

```basic
SP=256 // 스택 포인터를 0x0100으로 초기화
call Sys.init // 번역된 Sys.init 실행 시작
```

**Sys.init** : 메인 프로그램의 메인 함수 호출 → 무한 루프 → 번역된 VM 프로그램 실행

0 comments on commit ea27937

Please sign in to comment.