Addressing Mode - Indirect, Indexed, Immediate

지금까지 LMC는 명령어들을 통해 주소를 받고 그 주소에 해당하는 메모리의 위치를 활성화시켜 직접 접근해서 값을 가져왔다.

그러나 이 방식은 전체 메모리를 다 활용할 수 없다는 단점이 있다.

데이터는 십진수 3자리 값을 갖기 때문에, 실제로 주소로써 사용할 수 있는 값은 000 ~ 999 가 되지만, 명령어 3자리 중 Operator, Addressing Mode, Operand Register 를 묵시적으로 나타내는 OP Code 가 차지하는 길이가 있기 때문에 주소값으로 00 ~ 99 까지밖에 활용할 수 없다.

이를 해결하기 위해 간접 주소 지정 방식(Indirect Addressing)을 사용한다.


Indirect Addressing

Indirect Addressing은 C언어에서 배우는 포인터처럼, 또다른 Operand(주소값)를 담고 있는 주소를 가리키는 Operand이다.

즉, 메모리가 실제로 사용하려는 데이터에 접근하기 위해서 메모리를 한번 더 읽어서 접근한다.

현재 LMC에서는 7XX 명령어를 사용하여(), XX 주소에는 “실제 데이터가 담긴 주소값”이 담겨있다.

명령어 7은 (연산자 ADD, Indirect Addressing, 레지스터 A)를 묵시적으로 표현한다 - 어셈블러가 명령어를 조립하는 과정에서 * 표시가 붙은 피연산자는 7로 조립하는 것이다.

예를 들어, (ADDA, *90) 명령어는 어셈블링 과정에서 명령어 790으로 변환되고, LMC가 이를 실행시킬 때는 우선 90 번지의 값을 MemoryRead로 가져온 뒤, 해당 주소값을 다시 MemoryRead 한 값과 레지스터 A를 연산한다.

이렇게 할 경우 90번지에는 000 ~ 999 까지의 세자리 값이 다 들어갈 수 있기 때문에, 메모리 공간을 알뜰살뜰하게 사용할 수 있다.

Indirect Addressing 이 없을 경우, 이와 유사한 방식의 프로그램을 짜기 위해서는 런타임 중에 실행코드가 변경되는 일이 발생한다.

예를 들어 90 ~ 92 번지에 있는 데이터들을 반복문을 통해 A에 계속 더한다고 했을 때, ADDA에 해당하는 실행코드 값이 (390 -> 391 -> 392) 처럼 변경된다.

그러나 간접 주소 지정을 사용한다면, 실행 코드가 아니라 포인터 변수의 값만을 바꾸면 되기 때문에(780) 더 안전하고 권장되는 방식이라고 할 수 있다.


Indexed Addressing

Indexed Addressing 은 8XX 처럼 표현되며, 어셈블러가 인식하게 하기 위해서는 피연산자에 @을 붙인다.

(ADDA, @90)처럼 @가 붙은 피연산자를 인식할 경우 어셈블러는 이를 890 으로 조립하고, 명령어코드 8에는 (ADD 연산자 + Indexed Addressing + 레지스터 A와 X)를 사용한다는 약속이 묵시적으로 되어있다.

이 때 새로운 레지스터 X 가 등장하였는데, X는 인덱스 값만을 담는다.

8XX 에서 입력받은 주소와 레지스터 X의 인덱스값을 더한 값을 주소로써 표현하는 것이 Indexed Addressing 이다.

만약 현재 레지스터 X 에 001 이 담겨있고, 이번 명령어가 890 일 경우에 IR이 이를 해독해서 MAR 에 091 을 담고, MemoryRead 를 발생시켜 91번지 주소에 있는 값을 A 레지스터와 더하는 것이다.

이러한 방식은 배열이나 테이블 등을 다룰 때 유용하다.


Immediate Addressing

Immediate Addressing은 메모리 Read 등을 발생시키지 않고 즉시 주소를 지정하는 방식이다.

OP Code 는 52, 53, 54 등 두자리로 지정되며, 나머지 한자리의 값을 받아서 레지스터 A를 직접 변경시킨다.

52,53,54는 순서대로 Load, Add, Sub 을 나타내며, 어셈블러에게 표시할 때는 # 을 붙인다. 예를 들어 (LDA, #1) 은 521 로 조립되고, 이 명령어는 레지스터 A에 001 을 Load 한다.

즉 각각의 OP Code 들은 묵시적으로 (연산자(LD/ADD/SUB), Immediate Addressing, 레지스터 A)를 사용한다는 뜻을 담으며, 나머지 한자리 숫자가 Operand 가 된다.

이 때 입력받는 한자리 값을 IMMED(디코딩변수)로 지칭하는데, 자릿수가 한개밖에 없기 때문에 표현할 수 있는 수의 크기에 제한이 있다.

그러나 Effective Address(MAR 주소 활성화) 계산이 필요 없어서 0 ~ 9 까지의 한 자리 숫자를 Load 하거나 연산하는데 비용이 적게 든다는 장점이 있다.

53, 54 등을 내부적으로 구현할 때 단순히 A = A + _ 처럼 연산하지 않고, alu() 함수를 사용해야 PSR 의 상태 플래그들이 제대로 반영된다.