제 2 장 어셈블러(Assemblers)

Download Report

Transcript 제 2 장 어셈블러(Assemblers)

5 장 컴파일러(Compilers)
5.1 기본적인 컴파일러 기능(Basic
Compiler Functions)
 용어
-
-
-

문법(grammer): 적법한 문장의 형식
(syntax of legal statements)
토큰(token): 언어의 기본 구성 단위
(fundamental building blocks of the
language)
어휘 분석(lexical analysis): 다양한 토큰들
을 인식하고 분류
스캐너(scanner): 어휘 분석을 하는 컴파
일러의 한 부분
구문 분석(syntactic analysis): 문법으로 표
현된 언어 구조로 인식
파서(parser): 구문 분석을 하는 컴파일러
의 한 부분
5.1.1 문법(Grammers)
 비교

I := J + K
I := X + Y
- 문법은 같음
- 의미 다름
- 기계어 명령 다름
BNF(Backus-Naur Form)
-
• ::= 는 ~로 정의됨(is defined to be)
• ::= 왼쪽은 언어 구조(language
construct) 이름
• ::= 오른쪽은 구조에 대한 설명
• 괄호 < 와 > 로 묶인 문자열은 비단말
기호(nonterminal symbols)
• 괄호 < 와 > 로 묶이지 않은 문자열은
단말 기호(terminal symbol)
• id: identifier, int: integer
• 공백은 의미 없음
• 재귀적, 순환적(recursive)
기본적인 번역 작업의 세 단계
-
어휘 분석(lexical analysis)
구문 분석(syntactic analysis)
코드 생성(code generation)
(단일 패스이거나 코드 최적화 (code
optimization) 또는 기타 분석과정 있기도)
시스템 프로그래밍
문법 표현 방법
-
단순화된 Pascal 문법: p228 Fig.5.2
(예) <read> ::= READ ( <id-list> )
•
•
비단말 기호: <read>, <id-list>
단말 기호: 토큰 READ, 토큰 (, 토큰 )
1

파스 트리(parse tree) 예: p230 Fig.5.3
= 구문 트리(syntax tree)

<ident> ::=
<letter> | <ident><letter> | <ident><digit>
<letter> ::= A | B | C | … | Z
<digit> ::= 0 | 1 | 2 | 3 |… | 9
- 위의 문법으로 파싱하면 A, B, 0, 1 등
하나의 문자를 토큰으로 인식
ALPHA, BETA
READ ( VALUE )
VARIANCE :=
SUMSQ DIV 100 - MEAN * MEAN


연산 순위(precedence): 5.1.3절
모호한 문법(ambiguous grammar)
-
주어진 문장에 대하여 하나 이상의
파스 트리가 존재
모호하지 않아야 함
식별자 문법

스캐너가 하는 일
-
• 다중문자 식별자(multiple-character
identifier)를 하나의 토큰으로 직접 인
식
• 출력은 일련의 토큰(a sequence of
tokens)
• 각 토큰을 고정 길이 코드(정수)로 표현:
p234 Fig.5.5
• 키워드나 연산자 아닌 경우 토큰 명시
자(token specifier) 결합: p236 Fig.5.6
• 토큰 명시자: 식별자 이름, 정수 값 등
• 식별자 인식되면 심볼 테이블에 등록
하고 토큰 명시자는 그 포인터로 설정
5.1.2 어휘 분석(lexical analysis)
 두 작업
-
프로그램 스캔(scanning the program)
• 키워드, 연산자, 식별자(identifier),
정수(integer), 실수, 문자열 등 인식
-
토큰 인식(recognizing the tokens)
• id 와 int 인식은 단일 토큰으로 직
접 인식
시스템 프로그래밍
토큰 인식
원시 프로그램 목록 출력
2

어휘 스캔 시 고려해야 하는 언어
특성들
-
특수 포맷
• FORTRAN 1-5열은 문장번호
• 빈칸이 토큰들의 구분자인지
(Pascal) 아닌지(FORTRAN)
-
키워드인 경우와 문자열인 경우


유한 오토마타 스캐너 모델링
(Modeling Scanner as Finite Automata)
유한 오토마타(finite automata)
-
• 원: 상태
• READ와 “READ”
-
-
-
문자열 안의 빈칸과 다른 부분의 빈
칸
FORTRAN: comma(,) 미리 조사
• DO 10 I = 1, 100
• DO 10 I = 1
FORTRAN: 키워드를 식별자로 사
용 가능
IF(THEN .EQ. ELSE ) THEN
IF = THEN
ELSE
THEN = IF
ENDIF
• 스캐너와 파서와의 상호 작용하여
문법에 맞는지 해석
시스템 프로그래밍
유한 개 상태(states)와 유한 개 천이
(transitions)의 집합으로 구성됨
그래픽한 표현
하나의 시작 상태(starting state)
하나 이상의 종결 상태(final states):
이중 원(double circle)
• 화살표 : 천이
• 레이블(label): 천이를 일으키는 입력
-
모든 토큰 인식(recognize) 가능
• 오토마타가 종결 상태에서 멈춘 경우
-
(예) p240 Fig.5.8
• (a): A-Z로 시작하고 A-Z와 0-9로 구
성된 식별자 및 키워드 인식
• (b): _(underscore) 포함한 식별자 인식
• (c): 앞 제로(leading zeros)를 포함하는
정수 문자열 인식
• (d): 앞 제로 없는 정수 문자열 인식
3

모든 토큰의 인식
-
유한 오토마타: p241 Fig.5.9
별도의 테이블 조사(table look-up)
필요
• 키워드 구별
• 식별자의 길이 제한 확인
• “END.” 인 지 확인
-
만일 아니면 “.”은 다음 토큰의 일
부로서 다시 스캔됨
5.1.3 구문 분석(Syntactic Analysis)
 구문 분석이란
원시 문장을 문법에 의해 기술되는
언어 구조로 인식
= 번역되는 문장에 대해 파스 트리를
생성하는 과정
-

파싱 기법
-
• “:=” 은 하나의 연산자로 인식

-

스캐닝 과정을 쉽게 시각화
(visualization)
구현이 쉬움
-
p241 Fig.5.10(b)
구현: 단지 테이블의 항목을 기록하
기만 하면 됨
HARD 한 걸 HARD 하게 하면 HARD해 진다.
HARD한 것은 아름답다.
시스템 프로그래밍
하향식(top-down): 루트에서 단말로
• 분석의 목표인 문법 규칙(루트)으로
부터 단말 노드들이 문장과 일치하
도록 트리 구성]
유한 오토마타를 테이블로 표현
-

• 문장에 해당하는 단말 노드들로부
터 시작하여 루트에 도달할 때까지
단계적으로 결합
유한 오토마타의 장점
-
상향식(bottom-up): 단말에서 루트로

연산자-우선순위 파싱(Operator Precedence Parsing)
-
상향식(bottom-up)
연속적인 두 개의연산자들을 조사
하여 어느 연산자를 먼저 처리할 지
결정
4
-
-
(예) A + B * C - D
< >
주위의 연산자들보다 높은 우선순
위 가진 부수식(subexpression)을 먼
저 스캔하여 문법 규칙으로 번역
루트에 도달할 때까지
우선 순위: p245 Fig.5.11

이동-감소 파싱(Shift-Reduce Parcing)
-
상향식(bottom-up)
인식되지 않은 토큰들은 스택에 저장
테이블의 항목에 의해 제어됨
두 가지 연산
• 이동(shift)
-
• ; > END 이거나 END > ;
-
이웃하여 나타나는 순서에 따라
• 감소(reduce)
• 관계 항목 없는 경우는 함께 나타날
수 없음(구문 오류)
• 모든 관계는 유일(unique)해야
-
(예) p246 Fig.5.12
(예) p248 Fig.5.13
• p230 Fig.5.3과의 차이
: <factor>와<term>이 <N1>에 해당
• <exp>, <term>, <factor>는 단지 연
산자의 우선순위를 표시하기 위해
문법에 포함되었음
• 우선순위 행렬에 이미 우선순위 포
함되어 있으므로 실제 파싱 중 이름
을 구별할 필요 없음
시스템 프로그래밍
현재의 토큰을 스택에
< 과 = 인 관계가 있는 연산자를 마
났을 떄
-
-
-
스택의 톱에 있는 심볼을 문법 규칙
에 따라 번역
> 인 관계가 있는 심볼을 만났을 때
(예) p251 Fig.5.14
LR(Left-to-Right) 문법에 적용 가능
• 인식될 심볼이 항상 스택의 톱에
-
LR(k)
• 가장 강력한 이동-감소 기법
• k: 파싱을 위해 조사하는 토큰들의 개
수(default: k=1)
-
SLR(Simple LR)
LALR(Lookahead LR)
5

재귀-하강 파싱(Recursive-Descent
Parcing)
-
-
• 문법이 여전히 재귀적
-
하향식(top-down)
비단말 심볼을 위한 프로시주어임
현 토큰으로 시작하는 입력의 부분
문자열(substring of the input)을 찾아
비단말 기호로 번역
-
재귀-하강 알고리즘
• (예) p254 Fig.5.16
(a) READ와 IDLIST 프로시주어
(id가 따르지 않은 comma는 오류)
(b) 파스 트리 구성 단계
(파스 트리가 루트로부터 구성됨)
선택 사항(alternative) 있을 경우
• 다음 입력 조사하여 선택
-
왼쪽 재귀(left-recursion) 문제
• (예) p256 Fig.5.17
• 규칙 6의 <id-list>에서 두번째 선택
사항(<id-list>, id) 선택하면
-
<id-list> 재귀 호출
<id-list>의 선택사항 중 하나가 <idlist>로 시작하므로 무한 루프
• 왼쪽 재귀 제거
-
<id-list> ::= id {, id}
{}: 생략되거나 한번 이상 반복
규칙 6과 동일
선택사항 제거
시스템 프로그래밍
<exp>는 <term>으로 정의
<term>은 <factor>로 정의
<factor>의 선택사항에 <exp>
• <exp>로부터 다시 <exp> 호출되는
과정에서 적어도 하나의 토큰 처리
• 성공하면 성공 알리고 토큰 포인터
를 인식된 부분 문자열의 다음으로
-
p228 Fig.5.2와 p253 Fig.5.15 비교
(a) ASSIGN 프로시주어
(b) 파스 트리 구성 단계
(p230 Fig.5.3(b)와 비교할 것)

상향식과 하향식의 조합도 가능
-
(예)
• 고수준(문장 분석): 재귀-하강 파싱
이용
• 저수준(산술식 구조 분석): 연산자
우선 순위 파싱 이용
6
5.1.4 코드 생성(Code Generation)
 코드 생성 기법
-
자료 구조
-

-
-
파서가 문법에 의해 문장을 인식하
면 해당 루틴이 수행되어 코드 생성
• 코드 생성 루틴(code-generation
routine)이라고도: 직접 목적 코드
생성

목적 코드 생성
문법의 각 규칙에 대한 루틴(의미
루틴) 집합 포함
• 의미 루틴(semantic routine): 언어
구조에서의 의미와 관련된 루틴
-

리스트: FIFO(First In-First Out)
스택: LIFO(Last In-Last Out)
LISTCOUNT: 리스트 안의 항목 개
수
토큰 명시자(token specifier) 이용:
S(token), S(id), S(int), p236
HARD 한 걸 HARD 하게 하면 HARD해 진다.
HARD한 것은 아름답다.
시스템 프로그래밍
SIC 어셈블러의 심볼 표현(symbolic
representation) 사용하나 기계어임을 기
억할 것
목적 코드 생성때 마다 LOCCTR 갱신됨
파서는 가장 왼쪽 부분 문자열 인식
• 연산자-우선순위 파서: 비단말 <Ni>로 치
환되는 순간
• 재귀-하강 파서: 성공 표시 반환 순간
-
(예) READ (VALUE); p298 Fig.5.12
• id VALUE 를 <id-list>로 인식한 후
• 문장 전체를 <READ>로 인식
• XREAD
-
표준 라이브러리
링킹 로더나 링크 편집기에 의해 목적 프로그램
과 링크됨
• XREAD의 인자 리스트(parameter list)
-
JSUB 다음에 정의됨
첫번 WORD는 READ의 변수 개수
워드의 주소는 레지스터 L에 복사됨
L은 인자들의 위치로 이용됨
L + 인자 리스트의 길이 = 복귀 주소
-
다음 WORD는 변수들의 주소
값
• id와 int 토큰 명시자는 리스트에 삽입되
고 목적 코드 생성시 리스트에서 제거됨
7

(예) <assign> 문 코드 생성: p264
Fig.5.19
-
(b) 의 <term>1 ::= <term>2 * <factor>
• 한 노드 명시자가 rA 이면 단순한 MUL
생성: 이 떄 피연산자의 주소는 다른 피
연산자의 노드 명시자
• 그렇지 않으면 GETA 호출: LDA생성 전
에 이전의 REGA 내용 저장 위해 STA
-
-
목적 프로그램의 마지막 부분에 생성되
는 임시 변수에(Ti)
임시 변수들은 레지스터 A의 이전 값과
연관된 노드의 노드 명시자는 임시 변수
지시하도록 변경
• <term>1의 값이 레지스터 A에 있음 알리
기 위해 S(<term>1)과 REGA 설정
시스템 프로그래밍
(b) 의 <assign>
• 배정될 값을 레지스터 A에 가져온 후
• STA 생성
• REGA 값 null 로 설정
(a): <assign>s 문 파스 트리
• 문장의 각 부분이 인식되어질 떄 코드 생
성 루틴 호출
• 레지스터 A에 남아 있는 결과 보존 필요
• 노드 명시자 S(<term>1) 은 rA
• rA: 연산 결과가 레지스터 A 에 남아 있음
• REGA: 생성된 코드에 의해 레지스터 A
에 남아 있는 파스 트리 상의 최상위 rA
노드
-
-
-
(b) 의 나머지 규칙
• 기계어 명령 생성 않음
• 상위 레벨 노드의 노드 명시자를 해당
값의 위치를 반영하도록 설정
-

(c): GETA 루틴
(d): 목적 코드의 심볼 표현(symbolic
representation)
(예) PROG 문 코드 생성
-
헤더 정보 생성:START, EXTREF 등
복귀 주소 저장 명령 생성
첫번째 실행 가능한 명령으로 점프 명
령 생성
<prog>가 완전히 인식될 때 임시 변수
에 기억 장소 할당
단일 패스 전방 참조와 같은 방식
라이브러리 루틴에 대한 외부 참조위
한 수정 레코드 생성
<for> 코드 생성
• <index-exp> 인식되어질 때 인덱스 변
수 초기화와 반복 중단 검사
• 스택으로 중첩 반복 허용
8
5.2 기계 종속적인 컴파일러 특성(Machine- 
Dependent Compiler Features)
 코드 최적화
-
-
프로그램 중간 형태(intermediate form)
을 분석 조작하여 최적화
원시문장이나 기계코드 조작 보다 쉬움
코드 최적화
-
불필요한 로드 및 저장 명령을 줄이
도록 재배열
중간값인 Ij 를 임시 변수나 레지스터
에 효율적으로 배정
5.2.2 기계 종속적인 코드 최적화
5.2.1 프로그램 중간 형태(Intermediate
(Machine-Dependent Code
Form of the Program)
Optimization)
 코드 최적화 위해 실행가능 명령을 4쌍
 코드 최적화 위한 레지스터 할당
(quadruples)의 연속으로 표현
-
operation, op1, op2, result
(예) SUM := SUM + VALUE
-
• VALUE를 레지스터에: 7번, 9번 이용
• i5를 레지스터에: 16,18번 이용
• p271 Fig.5.21, p274 Fig.5.22: 레지스
터 하나(레지스터 A)로 8개 중간값 중
6개(i5, i7 제외) 처리 가능
+, SUM, VALUE, I1
:=. I1, ,SUM
-
(예) VARIANCE := SUMSQ DIV 100 MEAN * MEAN
DIV, SUMSQ, #100, i1
*, MEAN, MEAN, i2
-, i1, i2, ,3
:=, i3, ,VARIANCE
-
(예) p274 Fig.5.22
시스템 프로그래밍
(예)
-
레지스터 할당 알고리즘
• 레지스터 값 사용 시점 알기위해 프
로그램 스캔
• 가장 오래 사용되지 않는 레지스터
값 대치: 레지스터 안의 값이 메모리
에 저장되어 있지 않으면 임시 변수Ti
에 저장(p266 GETA 참조)
9
-
레지스터 값 추적
• 기본 블록(basic block)으로 나눔: p276
Fig.5.23 흐름 그래프(flow graph)
-
입구(entry point)
출구(exit point)
점프 없는 일련의 4쌍(quadruples)
• 기본 블록 이동시 레지스터들의 모든
값을 임시변수에 저장

5.3 기계 독립적인 컴파일러 특징
(Machone-Independent Compiler
Features)
5.3.1 구조화된 변수(Structured
Variables)
 배열 선언과 기억장소 할당
-
코드 최적화 위한 4쌍(quadruples) 재
배열(rearrange)
-
• 10 워드 할당
-
(예) p277 Fig.5.24
다른 코드 최적화 가능성
-
특수 명령어의 사용
• 특수 반복 제어 명령
• 프로시주어 호출하는 단일 명령
• 자료구조 조작하는 단일 명령
-
기능 장치(functional units) 가진 CPU
사용
• 서로 다른 기능 장치 이용하는 명령들
을 동시에(병렬로) 실행되도록 재배치
시스템 프로그래밍
A : ARRAY [l..u] OF INTEGER
• u - l + 1 워드 할당
• 명령어 2개 절약
• 임시 변수 하나 절약

A : ARRAY [1..10] OF INTEGER
-
B : ARRAY [l1..u1, l2..u2]
• (u1 - l1 + 1) * (u2 - l2 + 1) 워드 할당

배열 저장 방법: p280 Fig.5.25
-
행 우선 배열(row-major order)
• 오른쪽 첨자부터 바뀜
• 대부분 언어
-
열 우선 배열(column-major order)
• 왼쪽 첨자부터 바뀜
• FORTRAN
10

배열 원소 참조
-
-
-
B : ARRAY[l1..u1, l2..u2] OF INTEGER
B[s1, s2]의 상대주소:
w * [ (s1 - l1) * (u2 - l2 + 1) + (s2 - l2) ]
대부분의 컴파일러가 인덱스 레지
스터에 배열 시작주소에 상대적인
주소를 인덱스 레지스터에 설정하
는 코드 생성
인덱스 주소지정(indexed
addressing) 사용: p282 Fig.5.26
1차원 배열
• A : ARRAY [l..u] OF INTEGER
• 첨자의 값: s
• 원소의 길이: w
• A[s]의 상대주소: w*(s-l)
(예)
A : ARRAY [1..10] OF INTEGER
A[I] := 5
• 코드
- I #1 i1
* i1 #3 i2
:= #5
A[i2]
• A[i2]의 의미: 인덱스 레지스터에
i2 값 적재하고 인덱스 주소지정방
식으로 A를 참조
시스템 프로그래밍
2차원 배열
w*[(건너뛸 행수)*(각행의 원소개수)+(건너뛸 원소개수)]
(예)
B : ARRAY[0..3, 1..6] OF INTEGER
B[I,J] := 5
• 코드
*
+
*
:=

I
J
i1
i3
#5
#6 i1
#1 i2
i2 i3
#3 i4
B[i4]
컴파일러가 배열 참조를 위해 코드를
생성하기 위해 알아야하는 정보
-
배열 원소 타입
배열 차원(dimensions)
배열 첨자(subscript)의 하한과 상한
11

FORTRAN 90의 동적 배열(dynamic
array)
5.3.3 기계 독립적인 코드의 최적화
(Machine-Independent Code
Optimization)
- 컴파일러가 위의 정보를 다 몰라도 되
는 경우
 공통 부분식(common subexpression)
INTEGER, ALLOCATE, ARRAY ( : , : ) :: MATRIX
을 제거
• MATRIX는 정수 배열임선언
ALLOCATE (MATRIX (ROWS, COLUMS))
• 컴파일러는 ROWS, COLUMNS의 값
모름
• 컴파일러는 직접 배열위한 코드 생성
못하고 배열 서술자(dope vector) 생성
• 배열 서술자
-
(예) p286 Fig.5.27
- 2*J 항을 한번만 계산하도록 코드
생성
- 중간 형태(intermediate form)를 분
석하여 공통 부분식 파악
• 5번과 12번 4쌍이 결과값 제외한
operation, op1, op2 들이 동일하므로
12번 제거하고 12전 결과값 i10에 대
한 모든 참조를 5번 4쌍의 결과값인
i3으로 대치
• 그 결과 6번과 13번의 4쌍도 결과값
제외하고 동일하므로 13번 제거하
고 i11을 i4로 대치
• 10번, 11번 4쌍도 3번, 4번 4쌍과 같
으므로 제거
첨자의 하한과 상한 넣을 자리 포함
배열의 차원
배열 원소 타입
배열 시작주소
• ALLOCATE 문장 실행되면 첨자의 상
한과 하한 값 등록
• 배열 참조위한 코드는 이 배열 서술자
의 값을 이용하여 상대 주소 계산
-
시스템 프로그래밍
4쌍들의 총수가 감소하면 프로그램
수행시간도 그만큼 감소
12

루프 불변값(loop invariant)을 제거
-

루프의 다음 반복에도 값이 변하지 않
는 부수식은 루프 진입 전 한번만 계산
p286 Fig.5.23 (a)의 2*J 항
Fig.5.23 (c)의 5번, 6번, 7번을 루프 이
전으로 이동
4쌍의 연산 총수
• (b) 181번(18*10+1)
• (c) 141번(14*10+1)
• (d) 114번(11*10+4)으로 감소

원시 프로그램을 다시 작성
-
연산의 강도 감축(reduction in strength)
-
-
• 이 강도 감축은 원시 코드 수준에서도
가능
-
Fig.5.23(a)를 다시 작성
T1 := 2 * J;
T2 := T1 -1;
FOR I := 1 TO 1 0 DO
X[I, T2] := Y[I, T1];
-
-

루프 불변값을 제거한 효과만
첨자로부터 상대주소를 계산하는 처리
와 관련된 최적화(Fig.5.23(b)의 3번, 4
번, 10번, 11번)는 불가능
Fig.5.23(a)의 원래 프로그램이 더 명확
시스템 프로그래밍
덜 효율적인(less efficient) 연산을 더
효율적인(more efficient) 연산으로 대
치
p288 Fig.5.28 (b)의 2번 (EXP, #2, I, i1)
로 2**I 연산하는 대신 (c)의 4번(*, i1,
#2, i1)처럼 이전 반복 값에 2를 곱하는
것으로 대치
p288 Fig.5.28 (b)의 TABLE(I)의 상대
주소 계산에서 3번(-, I, #1, i2)과 4번(*,
i2, #3, i3)의 3*(I-1) 계산을 (c)의 5번
(+, i3, #3, i3)처럼 이전 변위에 3을 더
하는 것으로 대치
• 첨자 계산 과정에서의 강도 감축은 원
시 코드 수준에서 수행될 수 없음
기타 기계 독립적인 최적화 방법
-
중첩법(folding): 컴파일 시 피연산자 아는
경우 컴파일러가 계산
루프 펼침(loop unrolling): 루프를 직선 코드
(straight-line code)로 변형
루프 합침(loop jamming): 루프 몸체를 합병
13
5.3.3 기억장소 할당(Storage
Allocation)
 정적 할당(static allocation)
-

-
재귀 호출 가능한 경우의 할당
프로시주어의 각 호출(invocation)
마다 모든 변수들에 대한 활성화
레코드(activation record)를 스택
구조로 생성
현재 호출된 프로시주어에 대한
활성화 레코드의 시작 주소는 일
반적으로 베이스 레지스터에 넣고
그 프로시주어의 변수들의 주소지
정에 사용
시스템 프로그래밍
p291 Fig.5.30
• B(베이스 레지스터): 현재의 활성화 레코드
의 시작주소
• PREV: 스택안의 이전 레코드 시작주소
• NEXT: 스택안의 사용가능 영역 시작 주소
• RETADR: 호출한 프로그램 안으로의 복귀
주소
• 호출자에게로 복귀할 때
목적 프로그램 안의 프로그래머정의 변수
재귀 호출 불가능하고 동적 할당
없는 언어에서 자주 사용
만일 재귀 호출하면 p290 Fig.5.29
(c)에서 처럼 RETADR 파괴
동적 기억 장소 할당(dynamic
storage allocation)
-
-
-
-
현재의 활성화 레코드는 삭제됨
PREV가 현재 활성화 레코드의 시작주소가
됨
B의 값 재설정
기억장소 자동 할당(automatic allocation of
storage)이라고도 함
• 컴파일러가 활성화 레코드 시작(B)에 상대
적인 주소값을 각 변수에 배정하고 베이스
상대주소지정 방식 이용한 코드 생성
• 컴파일러가 활성화 레코드를 관리하는 부가
적인 코드 생성
프롤로그(prologue)
- 각 프로시주어 시작시 활성화 레코드 생성
- 이전 레코드와 연결
- 포인터들 설정
에필로그(epilogue)
- 현재의 활성화 레코드 삭제
- 포인터들 재설정
14

프로그래머에 의한 동적 기억장소 할당 
-
FORTRAN 90의 동적 기억장소 할당
• ALLOCATE(MATRIX)
• DEALLOCATE(MATRIX)
-
PASCAL의 동적 기억장소 할당
• NEW(P): 변수를 위한 기억장소를 할당하
고 포인터 P가 생성된 변수를 가르키게
함
• DISPOSE(P): P가 가르키는 변수에 할당
된 기억장소를 해제
-
C의 동적 기억장소 할당
• MALLOC(SIZE)
• FREE(P)
• 변수들은 포인터 변수 P를 통한 간접 주
소지정으로 접근됨

기억장소 할당 메커니즘
-
OS가: NEW, MALLOC 등 문장이 OS에
대한 기억장소 요구로 번역됨
컴파일러와 연관된 실행시간 지원프로
시주어(run-time support pocedure)가
• 프로그램 시작시 OS로부터 heap(사용가
능 기억장소의 큰 블록)을 할당 받고 heap
으로부터의 할당은 실행시간 프로시주어
가 담당
• 쓰레기 수집(garbage collection)
시스템 프로그래밍
동적 기억장소 할당은 지연 바인딩
(delayed binding)
-
프로시주어 실행시 변수와 주소와의
관계가 지워짐
더 많은 융통성(more flexibility) 허용
더 많은 오버헤드(more overhead)
• 활성화 레코드 생성
• 간접 주소지정 사용
5.3.4 블록 구조의 언어(Block-Structured
Language)
 블록 구조 언어: ALGOL 등
 블록의 중첩(nesting of blocks)
-
한 블록은 그 블록을 포함하는 임의
의 블록에서 정의된 변수 사용 가능
변수들은 그것이 선언된 블록의 외부
에서는 참조될 수 없음
p296 Fig.5.31
• (a): 컴파일러가 블록에 번호 부여
• (b): 컴파일러가 블록 레벨 등 블록구
조 표 구성
15

식별자 선언
-


심볼 테이블에 블록번호와 함께 등록
다른 블록에 있는 같은 이름의 식별자
들은 체인으로 연결
-
식별자 참조
-
-
5.1절은 단일 패스 컴파일 방식
-
-
-
각 블록 진입시 활성화 레코드 안에
그 블록 안에 정의된 변수들 저장

둘러 싸고 있는 블록의 변수 접근위해
자료구조 디스플레이(display) 이용
디스플레이: 현재 블록을 둘러 싸고 
있는 모든 활성화 레코드들을 가르키
는 포인터들로 구성
p298 Fig.5.32와 p296 Fig.5.31: 활성화
레코드와 디스플레이 차이 비교
시스템 프로그래밍
파싱 프로세스에의해 구동
• 토큰 필요할 때 어휘 스캐너 호출
• 언어 구조 인식했을 때 코드 생성
루틴 호출
보통 자동 기억장소 할당 사용
-
블록 시작시작에 블록 디스플레이
초기화 코드 포함
블록 마지막에 이전의 블록 디스플
레이 복구 코드 포함
심볼 테이블 탐색: 현재 블록으로부터
한 단계씩 바깥에 둘러 싸고 있는 블 5.4 컴파일러 설계 선택 사항(Compiler
록들을 탐색
Design Options)
해싱(hashing) 이용하면 쉽게 구현됨 5.4.1 패스로 분할(Division into Passes)
• 해싱함수로 심볼테이블에서의 위치결

정
• 식별자 정의 체인에서 검색

블록 구조 언어의 컴파일러
5.2절, 5.3절의 최적화는 단일 패스
로 불가능
전방참조 허용하는 언어는 단일 패
스 불가능
-
X := Y * Z 의 변수들이 REAL과
INTEGER 형의 혼합인 경우 변환연
산 필요
16

단일 패스와 다중 패스
-
-
컴파일 속도가 중요하면 단일이 유리
실행 속도가 중요하면 다중이 유리
메모리 등 시스템 자원이 제한적일 때
는 다중이 유리
다중 패스의 경우 각 패스는 단순해져
서 이해, 작성, 테스트가 쉬워져 컴파
일러 작성 시간 단축
5.4.2 인터프리터(Interpreter)
 기계 코드 생성 않고 직접 수행하며
보통 실행이전 전처리(preprocessing)
어떤 언어는 인터프리터가 더 유리
-
-
SNOBOL, APL 등 컴파일된 프로그램
이 주로 라이브러리 루틴 호출들로
구성된 경우
실행 동안 동적으로 변수 타입과 변
수 이름의 스코핑이 바뀌는(dynamic
scoping) 경우
• 실행동안의 함수나 프로시주어의 호
촐 순서에 따라 참조되는 변수가 결
정됨
• 지연 바인딩(delayed binding)지원하
는 인터프리터로 더 쉽게 다루어짐
• (cf.)정적 스코핑(static scoping): 5.3.4
절
어휘분석과 구분분석 후 폴리쉬 후위
표기법(Polish postfix notation) 등의 내
5.4.3 P-코드 컴파일러(P-Code Compilers)
부 표현 형태로 변환
- 전처리는 기계코드로 번역하는 것보  인터프리터와 유사
다 빠르나 인터프리터로 번역된 프로
- P-기계(pseudo-machine)라는 가상 컴
그램의 실행은 느림
퓨터의 기계 언어 형태의 중간 단계
표현으로 변환된 후 인터프리터처럼
장점
수행됨
- 번역 속도가 중요한 경우 유리
- : p303 Fig.5.33
- 심볼 덤프(symbolic dump), 추적(trace)
-


등 디버깅 기능을 쉽게 지원
시스템 프로그래밍
17

장점
-
-


소프트웨어 이식성(portability): P-코
드 인터프리터를 가진 모든 컴퓨터에 
서 실행됨
P-코드 목적 프로그램은 종종 기계코
드 프로그램 보다 크기가 매우 작음
기계 코드 수행보다 느리므로 단일
사용자 대화형 환경에 유리
기계 언어 부루틴 사용도 지원
컴파일러-컴파일러 사용 과정:
p304 Fig.5.34
언어의 명세서 작성
-
토큰들 정의하는 어휘 규칙
원시 언어 문법
의미 루틴 또는 코드 생성 루틴
• 파서가 언어구조를 인식했을 때
마다 호출
• 파스 트리를 의미 루틴에 전달
Java 언어는 최근에 개발된 P-코드 컴 
파일러
장점

단점
5.4.4 컴파일러-컴파일러(CompilerCompilers)
 스캐너, 파서, 코드 생성기 자동 생성
-
컴파일러-컴파일러(compilercompiler)
컴파일러 생성기(compiler generator)
번역기 작성 시스템(translator-writing
system)
시스템 프로그래밍
-

손쉬운 컴파일러 작성과 테스트
메모리와 처리 시간에서 덜 효율
적일 수도
YACC(Yet Another CompilerCompiler)가 대표적
18
4. 전처리 지시자 실행, 매크로 확장,
#include 지시자 포함한 모든 소
스 파일은 단계 1-4 수행
5. 이스케이프 순서(escape sequence)
와 문자열은 해당 문자로 변경
5.5 구현 예(Implementation
5.5.1 SunOS C Compiler
 특징
-
C 전처리기(C preprocessor)
• 파일 포함(file inclusion)
• 매크로 처리(macro processing)
-

• \n은 newline으로
• \0dms ASCII 0으로
코드 최적화 위한 다양한 레벨을 사
용자가 정의 가능
어셈블된 코드 생성
ANSI가 정의하는 전처리 과정
(preprocessing phase)의 논리적 단계
6. 이웃하는 문자열은 접합
• “hello,” “ world” 는 “hello,
world” 로

-
1. trigraph 순서를 해당되는 단일 문자
로 대치,
• (예) ??< 를 { 로 대치
2. \ 와 newline으로 끝난 소스 라인을
\newline 삭제하여 다음 라인과 연결
3. 소스 파일을 전처리 토큰들과 빈칸
의 연속으로 구분, 코멘트 문은 하나
의 빈칸으로 대치, 전처리 토큰들은
일반적인 토큰과 헤더 파일 이름과
특수 숫자 형식 포함
시스템 프로그래밍
실제 번역 과정

어휘 분석(lexical analysis)
구문 분석(syntactic analysis)
코드 생성(code generation)
C 언어로 구현됨
-
효율적 목적 코드 생성 가능해야
성능 분석 도구(performance
analysis tools) 지원
19

4 레벨 최적화
-
O1

프로그램 분석 지원
-
• 최소한의 지역적(peephole) 최적화
• 컴파일 후 어셈블리 언어 수준에서
-
기본적인 지역적 전역적 최적화
래지스터 할당과기본 블록 합체
공통 부분식과 루프 불변값 삭제
대수적 단순화(algebraic simplification)
후미 재귀 삭제(tail recursion
elimination)
• 최소 크기의 코드 생성
• 디폴트임
-
• 기본 블록의 실행 횟수
• 컴파실행 시간 기록 메커니즘
O2
•
•
•
•
•
-
-
O3
O4
• 실행시간 단축하는 최적화이나 목적
프로그램의 크기는 다소 커짐
• 사용자 정의 함수 호출을 in-line code
로 자동 전환
-
함수 호출 오버헤드 제거
전환하는 함수는 사용자가 컴파일 선
택사항(compile-time options) 으로 유
도 가능
시스템 프로그래밍
SunOS 소프트웨어 도구들
• 컴파일 결과분석하여 프로그램 프
로파일(profile of program) 생성
• 프로그램 각 부분의 실행시간 백분
율등
• 함수 차원에서 목적 코드 재배열
-
• 실행시간 단축하는 최적화이나 목적
프로그램의 크기는 다소 커짐
• 루프 펼침
-
컴파일 선택 사항으로 실행에 관한
정보를 목적 프로그램에 삽입 가능
-
-
컴파일 시 각 함수들을 독립된 섹
션에 배치
프로파일 분석 후 함수들을 재링
크하고 재배치
향상된 참조 국부성(locality of
reference) 지원하여 가상기억장치
시스템에서 효율적
디버깅 도구의 연산위한 정보 생성
• 컴파일 선택 사항으로 목적 프로그
램에 소스 코드 포함시켜 심볼릭 디
버거의 연산 이용 가능
-
변수 갑
제어 실행
소스 파일 열람 등
20
5.5.2 GNU NYU Ada Translator
 GNU: Unix 호환 통합 소프트웨어
 GNAT(GNU NYU Ada Translator):
GNU 소프트웨어의 일부인 Ada 컴파
일러: p309 Fig.5.35 GNAT 전체 구조
-
-
SAST(Abstract Syntax Tree)로 분석
심볼 테이블 없음
코드 생성은 GCC(GNU C Compiler)로
self-compiler: 컴파일러가 컴파일하는
언어(Ada)로 작성됨
Ada 언어의객체 지향 특성
구문 분석(syntac analysis)
• hand-coded recursive descent parser에
의해
• 고도의 오류 보고(high-quality error
reporting)
• 고도의 오류 회복(sophisticated error
recovery system)
-
의미분석(semantic analyzer)
-
확장(expansion)
• AST를 GCC tree로 변환하기 쉽도
록 AST를 변경
-
Gigi(GNAT to GNU)
• AST를 GCC tree로 변환
-
GCC back-end
• 코드 생성
• 중간 표현(intermediate
representation) 이용
• 구성 파일(configuration file)에 목
표 컴퓨터의 특성 기술
-
레지스터 개수
바이트, 워드, 포인터의 크기와
배열 방법
명령어 세트는 RTL(register
transfer language)로 표현
GCC syntax tree가 RTL로 표현됨
RTL 표현으로 레지스터 할당과
공통부분식 제거 등 최적화수행
5.5.3 Cray MPP FORTRAN Compiler
• 이름과 타입 해석등 모든 정당성
(legality) 조사
시스템 프로그래밍
21
5.5.3. Cray MPP FORTRAN Compiler
 MPP(massively parallel processing)
-
-

고성능 응용(very high-performance
applications) 지원
응용의 일부를 병렬로 실행하기 위해
다수의 PE(processing element) 들을
할당
컴파일러가 데이터와 계산 작업을

PE들에 할당해야 함
MPP FORTRAN 컴파일러의 간단한
고수준(high-level) 작업 분배
(distributing work) 방법
-
데이터의 분배(distrinution of data)와
연관됨
예
DIMENSION A(256)
CDIR$ SHARED A(:BLOCK)
CDIR$ DOSHARED (I) ON A(I)
DO I = 1,256
A(I) = SQRT(A(I))
ENDDO
시스템 프로그래밍
-
p311 Fig.5.36처럼 데이터가 분배
되었다면 CDIR$(compiler
directive) DOSHARED에 의해 각
PE들은 동시에 수행을 시작하며
자신에게 분배된 데이터에 대해
서만 처리함. 이때 다른 PE들이
모두 종료되가를 자동적으로 기
다림
상세한 프로세스 제어를 위한 저
수준 특성들
-
-
-
N$PES: 프로그램에서 사용가능
한 PE들의 수
MY_PE: 함수 호출을 실행하는
PE들의 수(0 ~ N$PES-1): N$PES
에서 main제외한 부분집합
HIIDX: 특정 PE에 할당된 배열
의 최대 첨자
LOWIDX: 특정 PE에 할당된 배
열의 최소 첨자
HOME: 특정 배열의 원소들이
차지하고 있는 PE들의 수
22

병렬성과 직렬성
-
MPP FORTRAN 컴파일러의 동기화
도구
-
-
5.5.4 Java Compiler and
Environment
 Java
-
barrier
• BARRIER: 실행 멈추고 다른 PE들이
BAARRIER에 도착할 때까지 대기
• PE들의 망을 이용한 hardware signal로
구현
event variable
• SET-EVENT: event variable을 세트
• TEST-EVENT: event variable을 조사
• 공유 메모리에 데이터 값 저장하여 구
현
• PE들의 망을 이용하여 hardware signal
로 구현: eureka mode
시스템 프로그래밍
기타
• 다른 PE의 특정 메모리 영역 접
근하는 명시적 방법 등
병렬 구역(paralle region): 디폴트
직렬 구역(serial region)
CDIR$ MASTER
...
CDIR$ END MASTER
• 첫 번 PE에서 수행됨
• 다른 PE들은 idle 상태에서 대기

-
-
-
Sun Microsystmes 가 최근 개발한
프로그래밍 언어이자 운영 환경
인터넷 환경에서의 다양한 응용
을 지원
아무런 수정 없이 다양한 운영체
제와 하드웨어 플렛폼에 이식 가
능한 응용들을 Java로 개발 가능
C, C++로부터 파생
• goto와 pointer 전혀 없음
• 기억장소 관리는 전자동
• 데이터 변환(data conversion)은
자체 언어 기능이용하여 명시적
으로
• 강력한 타입 체크 기능
23
-
객체지향 언어
-
• C++ 보다 강력한 객체 지향
• 몇가지 기본 타입 제외하고는 Java
안의 모든 것이 객체
• 절차적(procedural)인 것과 객체 지
향을 결합한 것이 아닌 순수 객체
지향 가능
-
• 컴파일러는 바이트 코드 생성: Java
가상 기계(Java virtual machine)이라
는 기계독립적인 가상적인 기계
(hypothetical machine)를 위한 고급
(high-level) 코드
• Java 가상 기계는각 목표 컴퓨터 상
에 인터프리터나 실시간 시스템의
형태로 구현됨
• Java 인터프리터만 있으면 모든
Java 응용이 아무런 수정이나 재컴
파일 없이 수행됨
• Java 자체도 Jave로 쓰여짐: Java 인
터프리터가 있기만 하면 Java 컴파
일러 실행 가능
다중 스레드(multiple threads) 지원
• 응용의 다른 부분들을 병렬로
(concurrently) 실행
-
스레드1: 애니메이션 실행
스레드2: 음향 효과 제어
스레드3: 위도우 스크롤
• 스레드도 객체롤 구현됨
• Java 라이브러리가 스레드 시작 및
정지, 스레드 상태 조사, 스레드간
동기화 등 스레드 제어하는 기법
제공(라이브러리 수준 스레드)
시스템 프로그래밍
P-코드 인터프리터 접근
-
바이트 코드 접근
• Java 응용을 WWW 에 통합시킴
• Java 바이트 코드(일명 applet)는
HTML 페이지에 포함시킬 수 있음
(그림을 포함하는 경우 처럼)
• Java- 호환 웹 브라우저가 그 HTML
페이지를 볼 때 applet 이 다운로드
되어 브라우저에 의해 실행됨
24
-
Java 가상 기계
-
• 기본(primitive) 데이터 타입 지원
-
• 실행 환경 조사가 필요없게 하여
Java 인터프리터는 가능한한 빠를
수 있음
• 자동 쓰레기 수집(automatic garbage
collection) 은 낮은 우선순위의 백그
라운드 스레드로 수행
• 높은 성능 필요한 경우 Java 바이트
코드를 실행시간에 기계 코드로 번
역 가능: 이 경우 성능은 C나 C++
의 처리 경우와 거의 같음
1,2,4,8 바이트 정수
단일 및 이중 정밀도 부동 소수
16비트 문자 코드
• 기본 데이터 타입을 흉내(emulate)
• 바이트 코드는 피연산자가 0 또는
여러개인 1 바이트 목적 코드로 구
성
• 많은 명령어들이 스택에서 피연산
자를 취함(레지스터가 많지 않은
시스템에 유리): (예) iadd의 두 피연
사자를 스택에서
• 고급 연산 지원하는 단일 바이트 명
령: (예) 배열을 생성하는 단일 바이
트 명령
• 객체 지향 연산을 지원하는 단일 바
이트 명령: (예) 특정 타입의 새로운
객체를 생성, 객체 인스턴스 조사,
메소드 유발, 객체 안의 필드 조작
등의 단일 바이트 명령
시스템 프로그래밍
실행 성능
5.5.5 The YACC Compiler-Compiler
 YACC(Yet Another Compiler-Compiler)
-
Unix 시스템의 파서 생성기
Pascal, RATFOR, APL, C 등 프로그
램 언어의 컴파일러 생성에 이용
Lex: 스캐너(어휘분석기) 생성기
YACC: 파서(구문분석기) 생성기
25

p316 Fig.5.37 Lex 와 YACC
-
입력: let x = y * z
(a) LEX
• 왼쪽의 패턴 나오면 오른쪽의 C 언어
로 표현된 활동(action) 수행
• 토큰 리턴
• 테이블 생성
• 출력: LET ID ASSIGN ID MUL ID
-
(b) YACC
• 문법을 입력 받음
• 각 문법에 연관된 의미 루틴(semantic
routine)을 호출
• 각 의미루틴은 변수 $$ 에 결과 배정,
이전의 결과는 $1, $2 등으로 참조
• expr : expr MUL expr
{$$ = build(MUL, $1, $3)}
- 파스트리 일부 구성하여 $$에 배정
-
각 문법이 인식될 때마다 의미 처리
필요
상향식(bottom-up) LALR(1) 파싱 이용
훌륭한 오류 검출 지원
시스템 프로그래밍
26
시스템 프로그래밍
27