어재 수업 빼고는 하루종일 hack 기계어와 어셈블리어를 정리했는데

내용은 절반? 정도 밖에 못했는데 

시간에 들인거에 비해서 분량도 얼마 되지는 않았다..

 

 

 

 

아 뭔가 보다가 조금 이상하다 싶었는데

어제 내가 C명령어를 정리하지 않았었다.

 

 

 

C 명령어

C명령어는 연산 비트(comp, 7비트), 목적지 비트(dest, 3비트), 점프 조건 비트(jmp, 3비트) 세 부분으로 111accccccdddjjj 같이 구성된다.

 

(1) acccccc : 7비트로 ALU가 수행할 연산을 결정하는 comp 비트

* 위 표에 나오다 시피 a가 0일때와, 1일때 수행하는 연산이 따로 나눠져있다.

(2) ddd : 3비트로 ALU 연산 결과를 담을 목적지를 나타내는데 저장하지 않을지(null), M에 담을지(RAM[A]), D 레지스터에 담을지, A레지스터 D레지스터 둘다에 연산 결과를 담을지 등 이 세 비트의 값으로 결정한다. 

(3) jjj : 3비트로 이뤄진 어떤 조건에 따라 점프를 할지를 의미하는 비트로 000인경우 점프 안함, 001 인경우 JGT로 연산 결과가 0보다 클때 점프, 111일때는 연산 결과에 상관없이 무조건 점프하는 JMP 명령이된다.

 

 

C 명령어의 연산 comp

 

 2장에서 ALU 구현한걸 다시 떠올리면, 두 16비트 입력을 받도록 되어있었다. 그러면 이 두 입력을 가지고 어떻게 기계어로 연산을 할수 있을까? 첫번째 입력 x는 데이터 레지스터 D에 있던 값을, 두 번째 입력 y는 어드레스 레지스터 A로 지정한 데이터 메모리 레지스터 M에 담아둔 값을 사용한다.

(이부분이 조금 햇갈리긴한데 그냥 진행한다)

 

 

 

 

 한번 comp의 입출력,  ALU 상태 비트의 입출력 테이블을 같이 보면

comp 명령에서는 a가 0이고, cccccc가 001100일때 D의 값을 가져오고

ALU 상태 입력이 comp의 c비트와 동일하게 001100일때 x를 출력으로 하는걸 볼수있다.

 

 그러니까 c가 001100 이더라도 a가 0일때는 데이터 레지스터 D, 1일때는 데이터 메모리 레지스터 M에있는 값을 가져온다.

 

 

 

ex) 심볼릭과 기계어로 D에 31, RAM[24]에 13이 들어있을때  D + M 연산해서 RAM[24]에 저장하자.

  =>  RAM[24] = 31 + 13

 

심볼릭 기계어(가독성을 위해 4비트씩 띄워쓰기함)
//1.  RAM[24]에 13넣기
@13
D=A
@24
M=D

//2. D = 31
@31
D=31

//3. D+M 후 RAM[24]에 쓰기
@24
M=D+M
0000 0000 0000 1101  // A명령어 13
1110 1100 0001 0000  // C 명령어 A를 로드해서(110000), D에다 저장(010), jmp안함(000)
0000 0000 0001 1000 // 24
1110 0011 0000 1000 // D의 값을 M에 쓰기     RAM[24]에 13넣기 끝

0000 0000 0001 1111 // 31
1110 1100 0001 0000 // A에 저장된 31을 D에다가 넣기

0000 0000 0001 1000 // 24
1111 0000 1000 1000 // RAM[24] = D + M

 

 

주석과 띄워쓰기를 지워 정리하면 hack 컴퓨터에서

RAM[24] = 31 +13 연산을 하는 기계어는 아래와 같다.

 

0000000000001101
1110110000010000
0000000000011000
1110001100001000
0000000000011111
1110110000010000
0000000000011000

1111000010001000

 

 

JMP 비트 사용하기

C 명령어의 JMP 비트는 연산 결과에 따라 어드레스 레지스터 A에 지정된 주소의 명령어를 가져오는(점프)하는 역활을 한다.

 

JMP 예시.  참고  c 명령어 : dest = comp;jmp

- D의 값이 0과 같으면 (LOOP)로 점프하라

@LOOP

D;JEQ

 

 

 

ex) 1에서 N까지의 합 계산하는 어셈블리 (RAM[1] = 1 + 2 + ... +RAM[0]

// 변수 i, sum 초기화
@i
M=1
@sum
M=0
(LOOP) // loop문 시작
@i
D=M
// D(i)-M(R0) = 0이면  i가 R0의 값과 같다 = i가 N까지 도달하였다.

@R0
D=D-M 
 // 모든 수를 더하였으므로 루프를 그만하고 (STOP) 문으로 넘어간다.

@STOP
D;JGT
// STOP으로 점프하지 않았다면 루프를 진행하면 되니 sum = sum + i 연산 하자
@sum
D=M
@i
D=D+M
@sum
D=M
// sum + i 연산을 한 뒤 i = i+1을 하자

@i
M=M+1
// 다시 루프 시작으로 가자
@LOOP
0;JMP
(STOP) // 루프 종료 조건 충족시 아래의 루틴 진행
@sum
D=M
@R1
M=D
(END) 
@END
0;JMP

주석을 지우면 아래와 같다.

@i
M=1
@sum
M=0
@i
D=M
@R0
D=D-M 
@STOP
D;JGT
@sum
D=M
@i
D=D+M
@sum
D=M

@i
M=M+1
@LOOP
0;JMP
(STOP)
@sum
D=M
@R1
M=D
(END)
@END
0;JMP

 

 

A 명령어의 값은 RAM 데이터 메모리의 주소인가? ROM 명령어 메모리의 주소인가?

진짜 A 명령어와 C명령어의 내용이 너무 햇갈린다. C 명령어의 dst와 jmp 둘다 쓸수 있지 않은지, 둘다 동시에 쓴다면 C 명령어 앞에 @R3이 있다면 R3의 값을 가져와서 1. dst 비트에 따라 M or A or D 에다가 C명령어의 연산 결과를 담고, 2. R3으로 JMP 간다고 생각하면 될까? 아니면 dst와 jmp를 동시에 쓰지 않고 dst만 하던가 jmp만 하는지. 지금까지 본 내용들을 보면 jmp와 dst 를 동시에 쓰는것 같지는 않다.

 

 또 A 명령어의 값이 RAM과 ROM의 주소를 동시에 나타대나보니  C 명령어와 함께 너무 햇갈리게 되는데, 뒤에 오는 C 명령어에 M이 존재하는지 여부에 따라 A가 RAM 혹은 ROM의 주소를 나타내는지 판단할 수 있다.

 

뒤에 오는 C 명령어가 M을 사용하는 경우 => A 명령어의 값을 RAM의 주소로 쓴다

C 명령어로 점프를 사용하는 경우 => A 명령어의 값을 ROM의 주소로 쓴다

 

위의 두가지 경우 정도로 이해하고 넘어가자

 

 

 

 

hack 어셈블리어의 심볼

지금까지 본 심볼들은 숫자, 상수와 달리 의미를 가진 알아볼수 있는 문자였다. 어느 위치에 접근할 때마다. 숫자를 주소로 하여 사용하기도 하고, 위의 예시에선 i나 sum 같이 변수를 이용해서 값에 접근하기도 하였다. 근데 지금까지 본 어셈블리어에서는 i, 4 같은 숫자와 문자 뿐만아니라 R1, R3, (LOOP), (END) 같은 다른 것들도 있었는데 이 심볼들은 무엇일까? hack 어셈블리어에는 우리가 만든 심볼 외에도 미리 정의된 심볼들이 있다.

 

미리 정의된 심볼들

1. R0, ..., R15(가상 레지스터)

 hack cpu는 16개의 레지스터를 가지고 있으며 R0은 RAM[0] ~ R15는 RAM[15]이 주소를 가지고 있다. A 레지스터가 주소 값으로 사용 될 때 @3의 경우 @R3가 동일한 동작을 한다고 할수 있긴 하지만, 미리 정의된 심볼을 사용하여 @3은 (확실하진 않지만) 데이터 레지스터로 사용되고 있구나, @R3은 데이터 메모리 주소로 사용되구나를 짐작할수 있는 장점이 있다.

 

2. SP, LCL, ARG, THIS 등

 가상 레지스터 이외에도 스텍 포인터를 나타내는 SP, LOCAL 등 다른 미리 정의된 심볼들이 있지만 가상 머신을 배울때 다루므로 일단 넘어가자.

 

3. SCREEN, KBD

 hack 컴퓨터는 IO장치로 스크린과 키보드를 사용하고 있다. 이 장치들을 사용하기 위해서 memory maped IO, 그러니까 스크린의 메모리 영역에 값을 쓰면 화면상에 표시되고, 키보드의 특정 키를 누르면 해당 키와 매핑된 메모리 주소의 값이 1이되는 식의 형태인데 이 미리 정의된 심볼들은 스크린 매모리맵, 키보드 매모리맵의 시작 주소 base address를 나타낸다. 이 내용은 5장 쯤에 다룬다.

 

4. 라벨 심볼

 이 외에도 앞서 루프문 예제에서 봤듯이 (LOOP), (STOP), (END)와 같이 (내용)과 같은 형태의 심볼을 봤는데 이러한 심볼들을 라벨 심볼이라 한다. 이 라벨 심볼은 바로 다음에 나오는 명령어의 주소를 가리키고 있어 점프 시 라벨 심볼 뒤의 명령어를 시작하게 된다. 그리고 이 라벨 심볼은 대문자로 써야한다.

 

일반 변수 심볼

 앞서 4가지의 미리 정의된 심볼에 대해서 정리하였고, 이런 심볼들 외  i, sum, x같은 것들을 변수 심볼이라 하며 @3을 사용했을때는 숫자 주소라 했지만 @i 일때는 어느 주소를 의미하는지 아직 알아보지는 않았는데 이는 어셈블리 파트에서 배울 수 있다.

 

 

 

스크린이랑 키보드에 내용은 그냥 넘어가고

간단하게 어셈블리어 작성 예시도 위에 했으니 기계어 장 이론은 여기까지 하고

다음 글에서는 이번 장 과제를 정리하자

 

글 하나 하나를 내가 아는 데로 정리하면서 쓰다보니 몇시간이 걸리는데

실제 글 내용은 생각보다 너무 적다.

차라리 교재든 강의 ppt든 번역하는게 더 빠르겠다 ㅠㅠ

+ Recent posts