Introduction


Absolute Loader

Machine-Dependent Loader Features(Linking Loader)

Machine-Independent Loader Features

Loader Design Options


 

로드(Loading): 목적 프로그램을 실행하기 위해 메모리로 가져오는 작업.

재배치(Relocation): 원래 지정된 주소와 다른 주소로 로드될 수 있도록 목적 프로그램을 수정하는 작업

링크(Linking): 둘 이상의 분리된 목적 프로그램을 결합하고, 서로 참조할 수 있도록 정보를 제공해 주는 작업

 

Absolute Loader


For SIC Machine

 

절대 로더링크와 프로그램 재배치 같은 기능이 필요 없기 때문에 기능이 매우 간단하며 모든 기능은 단일 패스로 실행된다.

- 프로그램 이름, 시작 주소, 길이에 대한 정보를 담고 있는 헤더 레코드를 검사한다.

- 로더는 각 텍스트 레코드를 읽어와, 그 목적 코드를 메모리에 지정된 주소로 이동시킨다.

- 엔드 레코드를 만나면 로더는 프로그램 실행을 시작하기 위해 엔드 레코드에 지정된 주소로 점프한다.

목적 프로그램

Fig.2.3 와 같은 object program에서 우선  헤더 레코드를 확인하여 주소 1000부터 시작함을 확인하고, 107A만큼의 사용가능한 메모리 공간이 있는지 검사한다. 각 텍스트 레코드를 읽어와 해당 object code가 메모리에 지정된 주소로 이동하고  엔드 레코드를 만나면 시작 주소 1000으로 점프하여 프로그램의 실행을 시작한다. 해당 과정을 거쳐 메모리에 프로그램이 로드되면 메모리의 모습은 Fig.3.1과 같다.

 

메모리에 로드된 프로그램

텍스트 레코드가 정의되지 않은 메모리 위치는 x로 표시되었으며, 이 위치의 내용이 바뀌지 않았음을 나타낸다. 이 프로그램에선 버퍼 영역이다.

 

Algorithm for an Absolute Loader

알고리즘은 위에서 설명한 것과 같다. 다만, 목적 프로그램에서는 어셈블된 코드의 각 바이트가 문자 형태로 16진수를 사용한다. 예를 들어 STL 명령어에 대한 연산 코드(op code)는 14와 같이 문자의 쌍으로 표현된다. 이것이 로더에 의하여 읽어들여질 때, 2byte 메모리를 차지한다. 그러나 이 명령어가 실행되기 위해서는, 연산 코드가 로드될 때 16진수의 값 14를 나타내는 단일 바이트(1byte)로 저장되어야 한다. 목적 프로그램 레코드에서 바이트들의 각 쌍은 로드 동안에 한 바이트로 바뀐다. Fig 2.3의 각 문자는 목적 프로그램 레코드의 한 바이트를 나타내고, Fig 3.1(메모리)의 각 문자는 메모리의 16진수 한자리(half-byte)를 나타낸다.


A simple bootstrap loader(부츠트랩 로더)

For SIC/XE Machine

 

컴퓨터를 켜거나 다시 시작할 때, 부츠트랩 로더(절대 로더)라 불리는 특별한 로더가 실행된다. 이 부츠트랩 로더는 컴퓨터에 의해 실행되는 최초의 프로그램(보통 OS)을 로드한다.

Fig 3.3

부츠트랩 자체는 0번지에서 시작하며, 80번지에 운영 체제(또는 다른 프로그램)를 로드한다. 이 로더는 시스템의 초기 프로그램을 로드하는 유일한 상황에서 사용되기 때문에, 로드되는 목적 프로그램은 매우 단순한 형태(헤더 레코드, 엔드 레코드, 주소 또는 길이 같은 제어 정보가 없다.)로 나타내어 질 수 있다.  목적 코드는 80번지부터 시작하여 메모리에 연속적으로 로드된다. 모든 목적 레코드가 로드된 후에, 부츠트랩은 80번지(시작 주소)로 점프하여, 로드된 프로그램의 실행을 시작한다. 

 

Machine-Dependent Loader Features(Linking Loader)


절대 로더는 단순하면서도 효율적이지만 몇 가지 잠재적인 결함을 갖고 있다. 프로그램이 어셈블되었을 때, 메모리로 로드될 실제 주소를 프로그래머가 지시해 주어야 한다. 이는 SIC와 같이 간단한 기계를 고려한다면, 별 문제가 되지 않는다. 그러나 좀 더 발전된 SIC/XE 같은 기계의 경우 몇 개의 독립적인 프로그램들이 메모리와 여러 자원을 공유하면서 함께 실행되는데, 이것은 프로그램의 로드될 위치를 미리 알 수 없다는 것을 의미한다. 또한 절대 프로그램의 사용은 서브루틴 라이브러리의 효과적인 사용을 어렵게 만든다. 메모리의 효율적인 사용을 위해 필요로 하는 루틴을 정확하게 선택하고 로드하는 것이 중요한데, 모든 서브루틴들이 절대 주소를 가지고 있다면, 이러한 작업은 효과적으로 이루어질 수 없다. 따라서 메모리의 효율적인 사용을 위해 절대 프로그램 대신에 재배치(relocation) 가능한 프로그램을 작성해야 한다.

 

Relocation

프로그램을 재배치하는 기능을 수행하는 로더를 재배치 로더(relocation loader) 또는 상대 로더(relative loader)라 부른다. 목적 프로그램을 재배치하는 방법은 두 가지가 있다.

 

첫 번째 방법은 프로그램이 재배치될 때 수정되는 목적 코드를 나타내기 위해 수정 레코드를 사용하는 것이다. 명령어들의 대부분은 상대 주소 지정 또는 즉시 주소 지정을 사용한다.

실제 주소들을 포함하는 부분(상대 주소가 아니다.)은 15, 35, 65행이며 확장 명령어 형식을 사용하고 있다. 이 행들만 재배치의 영향을 받게 된다.

재배치를 위한 수정 레코드를 포함하는 목적 프로그램

재배치 동안에 수정되어져야 하는 각 값에 대한 수정 레코드가 있으며, 각 수정 레코드는 변경될 필드에 대한 시작 주소와 길이를 나타낸다.

 

수정 레코드 방식은 프로그램 재배치를 지정하는데 편리하지만 모든 기계 구조에서 사용하기에는 적합하지 않다. 예를 들어 SIC 프로그램의 경우 상대 주소 지정을 사용하지 않기 때문에 rsub를 제외한 모든 명령어에서 사용하는 주소는 프로그램이 재배치될 때 수정되어야 한다. 따라서 31개의 수정 레코드가 필요하며 이는 2배 이상 큰 목적 프로그램을 생성하게 된다.

이에 대한 대안으로 두번째 방법인 재배치 비트(Relocation Bits)를 사용하는 방법이 있다. 수정되어야 할 주소가 매우 많다면, 수정 레코드 대신에 재배치 비트를 사용하는 것이 더 효율적이다. 텍스트 레코드는 목적 코드의 각 워드에 연관된 재배치 비트가 존재하는 것을 제외하고는 이전의 목적 코드와 같다. 각 SIC 명령어는 1워드를 차지하기 때문에, 각 명령어마다 하나의 재배치 비트를 대응시켰다. 이 재배치 비트들은 텍스트 레코드에서 길이 필드 다음에 비트 마스크(bit mask)로 저장된다. 

목적 코드의 어떤 워드에 대응하는 재배치 비트가 1로 설정되어 있다면, 프로그램을 재배치 할 때 프로그램의 시작 주소가 해당되는 워드에 더해진다. 반대로 0이면, 수정이 필요하지 않다. 텍스트 레코드가 12워드(텍스트 레코드 한줄의 최대 길이, 36바이트)보다 작으면, 사용하지 않는 워드에 대응하는 비트는 0으로 설정한다. 따라서 비트 마스크 FFC(111111111100)는 재배치 동안에 목적코드의 10개 워드가 수정되어야 한다는 것을 나타내고 있다. E00(111000000000)은 처음 3워드만이 수정 대상이며 나머지는 수정될 필요가 없는 데이터 상수와 rsub 명령어를 표현하고 있다.

why a new recode? 를 살펴보면, 텍스트 레코드 후미에 공간이 있음에도 불구하고 새로운 텍스트 레코드로 시작하고 있다. 그 이유는 각 재배치 비트가 텍스트 레코드에서 목적 코드의 3바이트(1워드) 세그먼트와 연관되기 때문이다. 첫 번째 why의 경우 resw, resb와 같은 어셈블러 지시자가 명령어로 사용되었기에 목적 코드에 나타나지 않는다. 두 번째 why의 경우 F1이라는 1바이트 데이터 때문에 적절하게 재배치 비트와 일치시킬 수가 없게 된다. 따라서 목적 프로그램에서 새로운 텍스트 레코드로 시작된 것이다.


Program Linking

제어 섹션들은 함께 어셈블될 수도 있고 서로 독립적으로 어셈블될 수도 있다. 그러나 어느 경우이든 어셈블러 후에는 별개의 세그먼트를 갖는 목적 코드로 나타난다.(목적 프로그램이 여러 개 생성) 프로그래머는 연관된 제어 섹션 모두를 조합하는 논리적인 개체로서 프로그램을 생각하지만 로더의 관점에서는 이러한 프로그램은 존재하지 않고 단지 링크, 재배치 그리고 로드되어야 하는 제어 섹션만 있다. 로더는 어떤 제어 섹션이 동시에 어셈블된 것인지 알 수 있는 방법이 없고, 또한 알 필요도 없다.

 

Object Code of Control Section A

 

Object Code of Control Section B

 

링크와 재배치를 설명하는 프로그램 예시
Object Code of Control Section C

 

각 제어 섹션은 다음 항목을 정의한다. (EXTDEF)

  • PROGA: LISTA, ENDA
  • PROGB: LISTB, ENDB
  • PROGC: LISTC, ENDC

 

각 제어 섹션은 외부 기호에 대한 같은 참조 집합을 포함하고 있다.

  • REF1 ~ REF3: 명령어에 대한 피연산자
  • REF4 ~ REF8: 데이터 워드의 값

 

REF1 (LISTA)

  • PROGA (Control Section A): REF1은 프로그램 내에서 단순한 레이블 참조이다. 재배치나 링크에 대한 수정이 필요없다.
  • PROGB, PROGC (Control Section B, C): REF1이 외부 기호(LISTA)를 참조한다. 어셈블러는 주소 필드가 00000으로 설정된 확장 명령어 형식을 사용한다. PROGB, PROGC에 대한 목적 프로그램은, 프로그램이 링크될 때 주소 필드에 기호 LISTA의 값을 더하라고 로더에게 지시하는 수정레코드를 포함한다.

 

REF2 (LISTB+4)

  • PROGA, PROGC: 외부 참조(LISTB)와 상수의 덧셈으로 구성되어 있다. 어셈블러는 주소 필드가 00004으로 설정된 확장 명령어 형식을 사용한다. 어셈블러는 명령어의 주소 필드에 상수의 값을 저장하고, 로더에게 LISTB의 값을 이 필드에 더하도록 수정 레코드를 생성한다.
  • PROGB: REF2가 지역 참조이므로 재배치나 링크가 필요 없다. 

 

REF3 (#ENDA-LISTA) - 리스트의 길이를 나타내는 ENDA와 LISTA 사이의 차이를 값으로 갖는 즉시 피연산자

  • PROGA: 어셈블러는 이 값을 계산하기 위한 필요한 모든 정보를 가지고 있다. (ENDA, LISTA)
  • PROGB, PROGC: ENDA, LISTA가 외부 참조이다. 어셈블러는 주소 필드가 00000으로 설정된 확장 명령어 형식을 사용한다. +ENDA, -LISTA를 포함하는 두 개의 수정 레코드가 생성된다.

 

REF4 (ENDA-LISTA+LISTC)

  • PROGA: 어셈블러는 LISTC의 값을 제외한 모든 수식을 계산할 수 있다. 결과는 16진수 000014(ENDA:0054-LISTA:0040)에 +LISTC를 더하는 한 개의 수정 레코드를 생성한다.
  • PROGB: 어셈블러에 의해서 계산될 수 있는 항이 없다. 목적 코드는 초기값 000000과 세 개의 수정 레코드(+ENDA, -LISTA, +LISTC)를 포함한다.
  • PROGC: 어셈블러가 상대적인 LISTC의 값을 알 수 있다. 이 주소는 프로그램이 로드될 때 알려지는 실제 주소값은 아니다. 이 데이터 워드의 초기 값은 LISTC의 상대 주소인 000030(16진수)을 갖는다. 수정 레코드는 프로그램의 시작 주소인 PROGC를 더하고 ENDA를 더하고 LISTA의 값을 빼도록 로더에게 지시한다. (3개의 수정 레코드가 생성된다.)

 

REF4에 대한 수식은 PROGA에 대한 간단한 외부 참조, PROGB에 대해서는 좀 더 복잡한 외부 참조, 그리고 PROGC에 대해서는 재배치와 외부 참조의 조합을 표현하고 있다.

 

재배치와 링크 후에 REF4, 5, 6, 7, 8(데이터 워드)의 각각의 값은 세 프로그램에서 같은 원시 수식으로 표현되므로, 모두 같은 값(same value, not address)을 갖고 있게 된다.

 

PROGA의 REF4(ENDA-LISTA+LISTC)

REF4의 실제 주소는 4000(PROGA의 실제 시작 주소) + 0054(PROGA에 대한 REF4의 상대 주소) = 4054 이다.

LISTC의 실제 주소는 0040E2(PROGC의 실제 시작 주소) + 000030(LISTC의 PROGC에 대한 상대 주소) = 004112 이다.

REF4의 값은 000014(000054 - 000040) + 004112(address of LISTC) = 004126 이다.

 

PROGB의 REF4(ENDA-LISTA+LISTC)

REF4의 실제 주소는 4063(PROGB의 실제 시작 주소) + 0070(PROGB에 대한 REF4의 상대 주소) = 40D3 이다.

LISTC의 실제 주소는 0040E2(PROGC의 실제 시작 주소) + 000030(LISTC의 PROGC에 대한 상대 주소) = 004112 이다.

REF4의 값은 000000(초깃값) + 000014(000054 - 000040) + 004112(LISTC의 실제 주소) = 004126 이다. (PROGA의 REF4와 동일한 값)

 

PROGC의 REF4(ENDA-LISTA+LISTC)

REF4의 실제 주소는 40E2(PROGC의 실제 시작 주소) + 0042(PROGC에 대한 REF4의 상대 주소) = 4124 이다.

LISTC의 실제 주소는 0040E2(PROGC의 실제 시작 주소) + 000030(LISTC의 PROGC에 대한 상대 주소) = 004112 이다.

REF4의 값은 000014(000054 - 000040) + 004112(LISTC의 실제 주소) = 004126 이다. (PROGA, PROGB와 동일한 값)

명령어 피연산자의 참조 (REF1: LDA, REF2: LDT, REF3: LDX)

 

명령어의 피연산자인 참조의 계산된 값은 로드 후에 항상 같은 값을 나타내지 않는다. 그 이유는 로드 후에 PC 또는 베이스 상대 명령어에 대해서 생기는 추가적인 주소 계산이 있기 때문이다. 그러나 target address(TA)는 같다.

 

TA = PC(B) + disp

 

예를 들어, PROGA에서 REF1 참조는 변위 01D를 갖는 PC 상대 명령어이다.  이 명령어가 실행될 때, PC는 다음 명령어의 실제 주소인 4023(4000 + 0023) 값을 갖는다. 계산된 TA(목표 주소)는 4040(4023 + 1D)이고, PC는 항상 다음 명령어의 실제 주소를 갖고 있기 때문에, 이 명령어에 대한 재배치는 필요 없다.

PROGB에서 REF1 참조는 직접(실제) 주소를 포함한 확장 명령어 형식이다. 링크 후 이 주소는 PROGA에서 REF1 참조에 대한 TA와 같은 4040(4000 + 40: LISTA의 상대 주소)이다.

 

 


자료 출처

  • "System Software: An Introduction to Systems Programming" by Leland L. Beck

'computer science > System software || OS' 카테고리의 다른 글

Operating system (2)  (0) 2022.12.07
Operating system (1)  (0) 2022.11.22
Macro Processors  (0) 2022.11.20
Linkers and Loaders (2)  (0) 2022.10.30
조원준입니다