메모리와 명령어

메모리와 명령어

메모리 주소 공간

폰 노이만 구조에서는 주소 공간이 명령어 메모리(Instruction Memory)와 데이터 메모리(Data Memory)라는 두 부분으로 분리되어 있다. 또한 주소 공간의 크기는 CPU의 주소 버스의 크기에 따라 정해진다. 만약 주소 버스가 32비트인 시스템에서는 2^32개의 서로 다른 주소에 대한 식별자를 만들 수 있으므로 0부터 2^32-1까지의 주소범위를 제공할 수 있다. 일반적으로 운영 체제는 하나의 프로세스에 대하여 하나의 주소공간을 제공하며, 프로세스 내의 사용자 스레드들은 주소공간을 공유한다. 앞으로 만들 시스템에서는 폭이 16비트이고 주소 공간은 15비트, 최대 32K(2^15)개의 16비트 단어들에 주소를 할당할 수 있다.

레지스터

프로세서에서 가장 빠르게 접근할 수 있는 메모리이다. 일반적으로 현재 계산을 수행중인 값을 저장하는데 쓰인다.

데이터 레지스터 : 정수 값을 저장할 수 있는 레지스터

주소 레지스터 : 메모리 주소를 저장하여 메모리 접근에 사용되는 레지스터

범용 레지스터 : 데이터와 주소를 모두 저장할 수 있는 레지스터

부동소수점 레지스터 : 많은 시스템에서 부동소수점 값을 저장하기 위해 사용된다.

상수 레지스터 : 0이나 1 등 고정된 값으 저장하고 있는 레지스터

특수 레지스터 : 프로그램의 상태를 저장한다. 프로그램 카운터, 스택 포인터, 상태 레지스터 등이 있다.

앞으로 만들 시스템에서 사용할 레지스터이다.

A 레지스터 : 데이터와 주소를 저장하는 레지스터

D 레지스터 : 데이터를 저장하는 레지스터

A레지스터는 메모리에 직접 접근을 용이하게 하는 용도로 쓰인다. 그런데 앞으로 만들 시스템에서 명령어는 폭이 16비트이고, 주소는 15비트이므로 연산 코드와 주소를 한 명령어 형식에 다 집어넣기는 불가능하다. 따라서 주소를 명시하는 대신. M 이라는 이름의 주소로만 메모리 접근이 가능하도록 강제한다. M은 항상 A레지스터의 현재 값을 주소로 하는 메모리 내 단어를 참조한다.

명령어

CPU는 메모리에서 PC(Program Counter)가 가리키는 주소의 워드를 읽어와서 디코딩하고 op 코드를 확인하여 명령어를 실행한다.

그리고 앞으로 만들 시스템에서 사용 할 명령어의 구조는 다음과 같다.

A-명령어

A레지스터에 15비트 값을 설정하는 데 쓰인다.

예를들면 @5 명령은 0000000000000101와 동일하다.

A-명령어 : @value // value는 음수가 아닌 10진수 A-CCOMMAND

C-명령어

A-명령어와 함께 쓰이며, 만들 컴퓨터에서 가능한 모든 연산을 수행한다.

C-명령어 : dest=comp;jump // dest나 jump 필드는 공란일 수 있다. C-CCOMMAND

맨 왼쪽 비트 값 1은 이 명령어가 C-명령어 임을 나타내는 코드이다. 그 다음 두 비트는 사용되지 않고, dest=comp;jump의 의미는 다음과 같다. comp 필드는 ALU가 할 연산이 무언인지를 뜻한다. dest 필드는 계산된 값을 어디에 저장할지 가리킨다. jump 필드는 점프 조건으로, 다음에 불러와서 실행할 명령어가 무엇인지를 의미한다.

계산 필드(Computation Field) : D와 A 및 M 레지스터 상에서 미리 정해진 함수들을 계산한다. 계산할 함수는 명령어의 comp 필드에서 정의되는데, 1개의 a-비트 및 6개의 c-비트, 총 7비트로 표현된다. 예를들어 D|M 값을 계산하는 명령어는 1111 0101 0100 0000이다.

COMP-FIELD

목적지 필드(Destination Field) : comp 부분에서 계산된 값은, 3비트 dest 부분이 가리키는 몇 가지 목적지에 저장된다. 첫 번째와 두 번째 d-비트는 계산돤 값을 각각 A레지스터와 D레지스터에 자장할지를 결정하는 코드다. 세 번째 d-비트는 계산된 값을 M에 저장할지를 결정하는 코드다. 이 비트는 하나 이상이 1이거나, 또는 모두 0일 수도 있다.

점프 필드(Jump Field) : 컴퓨터가 다음에 수행할 일을 지시한다. 컴퓨터가 하게 될 일은 두 가지 중 하나다. 하나는 프로그램에서 다음번 명령을 불러와서 실행하는 것(기본 설정)이고, 또 하나는 프로그램 내 다른 곳에 위치한 명령을 불러와서 실행하는 일이다. 후자의 경우에 컴퓨터는 점프할 주소가 A레지스터에 이미 저장되었다고 가정한다.

JUMP-FIELD

A레지스터를 사용할 때 충돌

A레지스터를 M과 연계하여 다음번 C-명령어의 데이터 메모리 위치를 선택하는 데에도, 점프 주소와 연계하여 다음번 C-명령어의 명령어 메모리 위치를 선택하는 데도 활용할 수 있다. 그러므로 두 경우가 충돌하는 현상을 막으려면 점프가 포함된 C-명령어가 M을 참조하지 않도록 주의 깊게 프로그램을 작성해야 한다.

입/출력 조작

스크린

스크린은 512개 열 X 256개 행의 흑백 픽셀로 구성된다고 하자. 또한 스크린에 표시되는 픽셀은 RAM 주소 16384(0x4000)부터 시작하는 8K짜리 메모리 맵에 대응한다. RAM내에서 32개의 연속된 16비트 단어(word)로 표현된다. 그로므로 위에서 r번째 행, 왼쪽에서 c번째 열의 픽셀은, RAM[16384+r*32+c/16]애 위치한 단어의 c%16번째 비트로 매핑된다.

예:

// 스크린의 가장 왼쪽 위에 16 픽셀 길이의 선을 까맣게 칠한다.
@SCREEN // 레지스터 A가 스크린 맨 윗 행에서 가장 왼쪽 16개 픽셀에 매핑되는 단어를 가리키도록 설정
M=-1    // -1은 2진수로 1111111111111111이다.
키보드

RAM 주소 24576(0x6000)에 위치한 1단어 메모리 맵을 통해 물리적 키보드 장치와 통신한다. 실제 키보드에서 키가 눌릴 때마다, 눌린 키의 16비트 ASCII 코드가 RAM[24576]에 기록되는 식이다.

곱셈 프로그램

R0와 R1이 입력으로 주어지고 R0 * R1을 R2에 저장하는 프로그램이다. R0, R1>=0, R0 * R1 < 32768이라 가정한다.

@R2
M=0         // Initialize R2 = 0
(LOOP)
    @R1
    D=M
    @END
    D;JLE   // if D <= 0 then Jump to @END
    @R0
    D=M     // D = R0
    @R2     
    M=D+M   // R2 = R0 + R2
    @R1
    M=M-1   // R1 -= 1
    @LOOP
    0;JMP   // Jump to @LOOP
(END)
    @END
    0;JMP   // Inifinite loop

I/O 조작 프로그램

키가 눌리면 스크린을 검게 만드는 프로그램이다.

(LOOP)
    @R0
    M=0     // Initialize R0 = 0
    @KBD
    D=M     // D = Memory[KBD]
    @SETWHITE
    D;JEQ   // if D == 0 then Jump to @SETWHITE
    @SETBLACK
    0;JMP   // else Jump to @SETBLACK
    
(SETWHITE)
    @8192
    D=A
    @R0
    D=D-M   // D = 8192 - R0
    @LOOP
    D;JEQ   // if D == 0 then Jump to @LOOP
    @R0
    D=M     // D = R0
    @SCREEN
    A=D+A   A = R0 + @SCREEN
    M=0     // SET Word to 0000000000000000
    @R0
    M=M+1   // R0 += 1
    @SETWHITE
    0;JMP   // Jump to @SETWHITE

(SETBLACK)
    @8192
    D=A
    @R0
    D=D-M   // D = 8192 - R0
    @LOOP
    D;JEQ   // if D == 0 then Jump to @LOOP
    @R0
    D=M     // D = R0
    @SCREEN
    A=D+A   // A= R0 + @SCREEN
    M=-1    // SET Word to 1111111111111111
    @R0
    M=M+1   // R0 += 1
    @SETBLACK
    0;JMP   // Jump to @SETBLACK