Suhwanc

이번 Two-pass Assembler는 시스템 프로그래밍 과목에서 항상 텀 프로젝트로 나왔던 부분이다.

다른 학교도 그래서인지.. 구글에 "two-pass assembler in github"라고 치면, 아주 글로벌하게 프로젝트 코드가 나오는 것을 볼 수 있다 😀

 

 

어셈블러란?

 

  • 말 그대로, 조각 난 것을 모아준다는 의미
  • 어셈블리 언어로 작성된 코드를 기계어로 번역해줌
  • 1대 1 대응이 일어난다.

 

기계어를 저장하는 방법

 

  • 위로 올라갈수록 높은 주소 → 위로 올라가면서 저장이 된다. (little-endian 방식)
  • ARM은 little, big 둘 다 지원하지만, 기본이 little으로 되어 있다.

예시)

ex. 0x8080 : e3a00000

 

 

ARM Instruction Set Format

 

위 두 그림은 arm에서 어셈블리 코드를 기계어로 변환하고 싶을 때, 또는 그에 대한 코드를 해석할 때

알아야 하는 기본 중에 기본이다. (외우는 건 아니고, 볼 줄만 알면 된다.)

 

 

왜 Two-Pass Assembler라는 이름이 붙었을까?

 

Two-Pass란 말 그대로 2번 지나간다는 건데, 이는 어셈블리어로 작성된 코드를 2번 순회하면서

첫 번째 순회때 부족한 부분을 채워준다는 의의가 있다.

 

예를 들어 다음과 같은 상황일 때, 첫 번째 순회 때는 "blt else"에서 "else"가 무엇인지 모를 것이다.

(이 else는 c, python의 else가 아니라 사용자의 함수입니다!)

 

하지만, 만약 else를 첫 번째 순회 마지막에서 어디에 저장해 두고 다음 순회를 하면 "blt else"를 만나자마자 알 수 있을 것이다.

 

 

Two-Pass Assembler 예시

 

1. Pass 1

첫 Pass 단계에서는 다음과 같은 Symbol Table이 만들어지게 되고,

8084번째 주소에 있는 명령어 코드는 아직 완성이 안된 상태일 것이다.

 

2. Pass 2

두 번째 Pass 단계에서는 만들어진 Symbol Table을 이용해 adr, ldr 같은 정규 명령어가 아닌 명령어들을 처리하는 과정을 보여준다.

위 그림을 보면 원래 adr r1, msg 였던 8084 줄이 -> add r1, pc, #(msg - 808c)로 바뀐 것을 볼 수 있는데,

원래 adr이란 것은 실제로 ARM 명령어 디코더에 정의되어 있는 명령어가 아니라, 어셈블러에서 지원하는 건데, 실제로 어셈블러를 만들고자 하면 우리가 직접 만들어야 하는 부분이다.

 

adr 명령어의 표현식은 ADR Rd, <expression>으로, <expression>의 주소 값을 Rd에 저장한다는 의미이다.

따라서 adr r1, msg는 msg 주소 값을 Rd에 저장해야 하고, msg 주소 값은 상대 주소로 가져와야하기 때문에

현재 pc와 msg 절대 주소 값의 차이를 pc에 더해주면 된다.

 

그런데, arm은 파이프라인 방식을 사용하고 있기 때문에 현재 8084가 execute 단계지만, 실제 pc는 808c에서 fetch를 수행하고 있으므로 pc는 808c가 된다.

 

(예시 그림)

 

 

계속되는 의문 : 2 pass로 충분한가?

 

다음 예시를 보자.

다음은 ldr, = format을 2 pass로 처리하는 과정을 알려준다.

 

1 pass

ldr,= format 명령어를 만난 경우, 범위가 넘어갈 수 있기 때문에 <expression> (msg) 은 상대 주소로 처리해주어야 한다.

(범위가 넘어가는 정수는. ltorg를 이용해 처리해준다.)

"msg"라는 symbol은 아직 정의되지 않은 상태이므로, =msg대신 msgaddr로 바꿔주고
. text section 맨 밑에. word 키워드로 정의를 함과 동시에 symbol table에 키워드를 저장해둔다. (아직 주소는 모르기에 공란)

(msgaddr :. word msg)

 

이후. data section에서 msg를 만났다면, symbol table 주소를 알맞게 채워준다.

이때 symbol table은 비로소 (msgaddr : addr) 형식이 완성될 것이다.

 

2 pass

이제 명령어는 ldr, r1, msgaddr로 바뀌었고, 현재 symbol table에는 msgaddr의 주소 값이 저장되어 있기 때문에 이를 이용해 msg에 접근 가능하다.

'System Programming(ARM)' 카테고리의 다른 글

7. Linking  (2) 2020.12.15
11. System-Level I/O  (0) 2020.12.15
8. Two-pass Assembler  (0) 2020.12.06
9. Exceptional Control Flow(흐름 제어)  (0) 2020.12.03
[ARM] Signal Handling  (0) 2020.12.03
10. Signals  (0) 2020.12.03