From ea27937eddea5bffca282e3e96a80b736385f8f2 Mon Sep 17 00:00:00 2001 From: Daeun Kim <65665065+jkde7721@users.noreply.github.com> Date: Tue, 14 Feb 2023 15:14:52 +0900 Subject: [PATCH] =?UTF-8?q?Chapter08=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08/README.md | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 08/README.md diff --git a/08/README.md b/08/README.md new file mode 100644 index 0000000..08187aa --- /dev/null +++ b/08/README.md @@ -0,0 +1,227 @@ +# Ch08 가상 머신 II: 프로그램 제어 + +### 고수준 언어의 세 가지 특성 + +1. 고급 연산을 필요에 따라 자유롭게 정의 가능 +2. 서브루틴을 기본 연산처럼 자유롭게 사용(호출) 가능 +3. 호출된 서브루틴이 실행되고 나면 그 종료 제어가 코드 내의 다음 명령으로 반환 + +
+ +### 서브루틴 호출 시, 필요한 처리 + +1. 호출자에서 호출된 서브루틴으로 **매개변수 전달** +2. 호출된 서브루틴을 시행하기 전에 **호출자 상태 저장** +3. 호출된 서브루틴의 **지역 변수에 공간 할당** +4. 호출된 서브루틴을 실행하기 위해 **점프** +5. 호출된 서브루틴의 **결과값을 호출자로 반환** +6. 값이 반환될 때, 호출된 서브루틴이 점유한 메모리 공간 재활용 +7. **호출자 상태 복구** +8. 호출자 코드에서 이전에 점프했던 지점 바로 다음 코드를 실행하기 위해 **점프** + +
+ +## 8.1.1 프로그램 흐름 제어 + +컴퓨터 프로그램은 한 명령어씩 순차적으로 실행하는 방식이 기본 + +- **goto destination** : 프로그램 내 특정 위치부터 실행 지속 + + *위치 설정 방식 : 다음에 실행될 명령어의 물리적 주소 지정하는 방식 + + (코드 내 특정 지점을 뜻하는 **기호 레이블**을 통해 점프할 위치 지정) + +- **if-goto destination** : 불 조건문이 참일 경우만 점프, 거짓이면 원래 프로그램 흐름대로 바로 다음번 명령 실행 + +
+ +### 저수준 제어 흐름 + +```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 + ... +``` + +
+ +## 8.1.2 서브루틴 호출 + +- 고수준 연산 단위 = 서브루틴, 프로시저, 함수, 메서드 +- 기초 명령(내장형 명령, add)과 고수준 연산(사용자 정의 서브루틴, power)은 같은 방식으로 **인수 처리**하고 **값 반환** + + (차이점 : 서브루틴 앞에 **call** 키워드 쓰임) + +- 호출 및 반환 논리의 단계적인 특성 : 서브루틴 호출이 아무리 많이 중첩되어 있더라도, 어느 한 시점에는 중첩된 서브루틴들 중 맨 위의 것만 실행, 그 아래 다른 서브루틴 호출들은 현재 실행되는 서브루틴이 종료되기를 기다림 + +- **프레임**(frame) : 서브루틴의 **지역 변수**, 서브루틴이 연산할 **인수**들, **작업 스택**과 연산을 지원하는 **메모리 세그먼트** 통칭 +- **전역 스택**(global stack) : 현재 서브루틴과, 그 서브루틴의 반환을 대기하는 다른 모든 서브루틴들의 **프레임**을 담고 있는 메모리 영역 (현재 서브루틴의 작업 스택이 전역 스택의 맨 위에 위치) + +
+ +### 저수준에서 call xxx 연산 구현 + +1. 호출자의 프레임을 스택에 저장 +2. 호출된 서브루틴의 지역 변수에게 스택 공간 할당 +3. 실행할 코드로 점프 + + (**call** 명령에 명시된 서브루틴의 메모리 주소를 확인하고 그 주소로 시작하는 실행 코드로 점프) + +- 호출된 서브루틴에서 **return** 명령으로 반환할 때 → 반환될 주소 명령에 표시X + + ⇒ 현재 서브루틴을 호출한 call 명령이 프로그램 어디에 있든지 간에 그 다음 명령으로 점프해서 실행 (**다음 명령의 메모리 위치** = **반환 주소**) + +
+ +## 8.2.1 프로그램 흐름 제어 명령 명세 + +- **label label** : 현재 함수 코드 위치에 레이블 붙임 (레이블이 정의된 함수 내부에서만 레이블 유효) +- **goto label** : 무조건 분기 명령, label 위치부터 실행 (점프할 위치는 같은 함수 내) +- **if-goto label** : 조건 분기 명령, 스택의 최상단 값을 꺼내서 그 값이 0이 아니면 label로 표시된 위치에서 계속 실행, 값이 0이면 프로그램 다음 명령 실행 (점프할 위치는 같은 함수 내) + +
+ +## 8.2.2 함수 호출 명령 명세 + +함수 이름의 번위는 전역적 (모든 파일 내의 함수 이름들이 공유, 함수 이름으로 서로 호출) + +- **function f n** : 이름이 f, 지역 변수가 n개인 함수 코드 시작 +- **call f m** : 함수 f 호출 (호출자가 스택에 m개의 인수 푸시) +- **return** : 호출한 함수로 반환 + +
+ +## 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 +- 반환되기 전 **값 하나 스택에 푸시** + +
+ +## 8.2.4 초기화 + +- VM 프로그램 = VM 함수들의 모음 +- VM이 실행될 때(또는 리셋될 때), 항상 **Sys.init** 이라는 인수 없는 VM 함수 먼저 실행!! +- **Sys.init** : 사용자 프로그램의 **메인 함수 호출** + +
+ +## 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로 점프 +``` + +
+ +### 어셈블리 언어 기호들 + +|**기호**|**사용법**| +|--------|----------| +|**functionName$label**|VM 함수 f 내의 label b 명령마다 전역적으로 유일한 기호 **f$b** 생성 (goto b, if-goto b 명령 번역 시, b 대신 전체 레이블 f$b 사용)| +|**(FunctionName)**|VM 함수 f마다 명령어 메모리 내 시작 포인트를 가리키는 기호 **f** 생성| +|**return-address**|VM 함수마다 **반환 주소**, 즉 함수가 호출된 곳 바로 다음 명령의 메모리 주소를 가리키는 유일한 기호 생성| + +
+ +### 부트스트랩 코드 : 컴퓨터가 부팅될 때 처음 실행되는 코드 + +- 번역된 .asm 파일이 준수해야 하는 규칙 + - VM 스택은 RAM[**256**] 위치부터 매핑 + - 실행되는 첫 번째 VM 함수는 **Sys.init** + +### 핵 컴퓨터의 부트스트랩 코드 + +```basic +SP=256 // 스택 포인터를 0x0100으로 초기화 + +call Sys.init // 번역된 Sys.init 실행 시작 +``` + +**Sys.init** : 메인 프로그램의 메인 함수 호출 → 무한 루프 → 번역된 VM 프로그램 실행