Assembler

1 minute read

어셈블러의 역할

어셈블리어로 쓰인 원시 프로그램을 입력 받아
목적 프로그램(object file)을 생성하는 일을 한다.

어셈블러 task 의 정의

어셈블러는 명령어를 생성한다.
연산 기호를 보고 기계어 명령으로 번역하고
심볼과 literal에 주소를 할당한다.

어셈블러는 코드를 두 번 읽는다. (2 pass assembler)
심볼이 정의되지 않은 상태에서 참조(reference) 하는 경우
그 값을 알 수가 없다.

패스 1 : 각 기호의 값만을 결정, 심볼 테이블 결정 (레이블과 그 값들)
패스 2 : 목적 프로그램 생성

어셈블러 설계 - 패스 1

패스 1은 심볼을 정의한다.

  1. 각 기계어의 길이를 결정한다. (앞서 배웠듯, 명령어의 길이는 용도, 피연산자마다 다양)
  2. 위치 카운터, 즉 현재 처리하고 있는 명령어 주소의 증가.
    (이는 분기 또는 함수 호출할 때 피연산자로 넣어줄 주소로 사용)
  3. 심볼의 값을 기억한다.

image

image

자료구조

  • 소스 프로그램
  • 명령어 테이블 (명령어의 유형과 길이 정보)
  • 삼볼 테이블
  • LC

*인텔은 CISC 프로세서로, 명령어들이 매우 복잡하다. *명령어의 표를 참조하고 유형을 분석하여 길이를 구한다.

어셈블러 설계 - 패스 2

패스 2는 목적 프로그램을 만든다.

  1. 심볼의 값을 찾는다.
  2. 명령어를 만들고 object 파일에 추가한다.
  3. 상수, 심볼등의 데이터를 만든다.

자료구조

  • 소스 프로그램 사본
  • 명령어 테이블
  • 심볼 테이블
  • LC
  • 목적 프로그램 출력

소스 토큰화

입력받은 어셈블리 소스를 필드 별로 나눠야 함
소스 라인 규칙 :

  1. 레이블 명령어 op1 op2
  2. 레이블 뒤에는 콜론(:)
  3. 빈칸, 쉼표, whitespace 에 대한 예외 처리

테이블

명령어 테이블은 크기가 정적임.

struct inst {
  char inst_name[4];
  char inst_code[4];
  int number_of_opnd;
}

struct inst inst_table[8] = {
  {"BEQ", "000", 2}, {"SUB", "001", 2}, ...
  {"ASL", "111", 2}};

반면 심볼 테이블은 동적

struct symbol {
  char symbol_name[9];
  int value;
  int lc;
} symbol_table[100];

struct symbol *ptr;
ptr = (symbol *)malloc(sizeof(struct symbol));