Zero Register
0번 레지스터는 항상 값을 0으로 유지하는 레지스터이다.
이 레지스터에 값을 쓰려고 할 수 있지만, 그 결과는 언제나 0이다.
이 레지스터는 다른 레지스터에 값을 옮기는 move 명령어를 구현할 때 0과 or 연산을 취해서 다른 레지스터에 값을 쓰는 식으로 move 명령어를 구현하는 용도로 사용된다.
또는 상수값을 레지스터에 쓰고자 할 때, 0과 더하기를 해서 원하는 상수값을 레지스터에 쓰는 용도로 쓸 수도 있다.
메모리에 접근하는 상황
우리의 컴퓨터는 stored program 방식을 사용하고 있다.
즉, 프로그램의 명령어와 데이터가 오프칩 메모리에 저장되어 있고, CPU는 명령어와 데이터를 메모리로부터 읽어와 연산하는 방식이다.
CPU가 메모리에 접근하는 상황은 크게 2가지이다.
첫번째는 명령어를 읽어들이기 위해 메모리에 접근하는 상황
두번째는 데이터를 읽고 쓰기 위해 메모리에 접근하는 상황
명령어를 읽어오는 상황
명령어를 읽는 과정은 어떻게 일어날까?
우선 명령어가 메모리의 어딘가에 저장되어 있을텐데, 어디에서 명령어를 가져오는지를 결정해야 한다.
이와 관련하여 PC (Program Counter) 라고하는 레지스터 파일과는 다른 별도의 레지스터가 필요하다.
(인텔에서는 인스트럭션 포인터라고 하기도 한다.)
PC는 내가 지금 읽어들이는 명령어의 메모리 주소값을 보관하고 있다.
그리고 명령어가 한줄 한줄 실행될 때마다, 값이 4씩 증가하면서 다음 명령어의 주소를 보관한다.
(명령어 하나의 크기가 32bit = 4byte 인데, 메모리는 byte addressable 하기 때문이다.)
하드웨어 종류마다 컴퓨터를 맨 처음 작동시킬 때, PC를 초기화하는 값이 다르다.
우리가 디자인할 MIPS 는 이 값을 0 으로 초기화 한다고 생각한다.
PC는 명령어가 메모리의 어디에 위치하고 있는지 주소만 갖고 있으므로, 해당하는 주소에서 명령어를 가져오려면 추가적인 동작이 필요하다.
이 동작을 instruction fetch 라고 하며, address bus 를 통해 PC 값을 실으면 data bus 에는 그 위치에 있는 명령어 데이터가 실리게 된다.
CPU는 이렇게 얻어는 명령어를 분석 (decode) 하고, 실행한뒤 (execute), 필요에 따라 레지스터에 값을 쓸 것이다. (Write Back)
그 뒤 앞서 말했듯 PC 값은 4 증가하여 다음 명령어의 주소를 가리키게 된다.
Word
워드는 몇개의 비트를 한번에 부르는 단위이다.
CPU의 종류에 따라 몇개 비트를 한번에 부를지 다른데, 보통 명령어 하나의 크기 (레지스터의 크기) 를 워드의 단위로 한다. (그래서 '단어' 인 것 같다.)
만약 64bit 컴퓨터라면 1word = 64bit 가 될 것이다.
우리는 32bit 명령어의 MIPS 를 다루므로 32bit = 1word 로 한다.
따라서 명령어를 읽을 메모리 주소는 명령어의 크기 단위인 4byte 단위로 접근해야 한다.
byte 단위로 읽고 쓰기
메모리는 byte-address 를 사용하므로 byte 단위를 읽고 쓸 때는 주소값이 1의 배수이면 된다. (즉 제약사항이 없다.)
lb (load byte), lbu(load byte unsigned)
8bit (1byte ) 단위의 값을 읽어 온다.
I-format 으로, rt, immd(rs) 형식으로 사용한다.
그런데 읽어온 데이터가 8bit 인데 반해 레지스터의 크기는 32bit 이므로 24bit 의 공간을 추가적으로 채워야한다.
lb 는 읽어온 8bit의 값을 레지스터의 가장 오른쪽에 채우고, 나머지 공간을 sign-extension 방식으로 채운다.
만약 zero-extension으로 채운다면 lbu 를 사용하면 된다.
sb (store byte)
8비트의 값을 메모리에 쓰는 명령어이다.
마찬가지로 I-Format 이고, rt, immd(rs) 형식으로 사용하여, rt 레지스터의 값을 rs+immd 위치의 메모리 공간에 쓴다.
sb 명령어는 32bit 사이즈의 레지스터 공간에서 LSB에 가까운 8bit 값 (= 하위 8bit)을 가져와 메모리에 쓴다.
메모리의 딱 1byte 공간에 쓰므로, extension 은 하지 않는다.
Endianness
32bit 레지스터에서 8bit를 읽어올 때, 값을 어떻게 읽어오는지는 하드웨어마다 다르다.
값을 읽어오는 방식은 크게 big-endian, little-endian 2가지가 있다.
이에 대해서는 지난 글에서 정리하였으니 이 글에서는 예시를 보려고 한다.
s0 레지스터에는 23456789 라는 값이 들어있다.
이 값을 메모리의 0번 주소위치에 1word 만큼 쓴다고 하자.
($0 은 0번 레지스터를 가리키는데, 0번 레지스터의 값은 항상 0이다. 따라서 주소값은 0 + 0 = 0)
빅 엔디안은 메모리의 낮은 주소에 레지스터상 큰 값 (MSB) 부터 저장하는 방식이다.
따라서 빅 엔디안은 메모리에 위와 같이 MSB 인 23을 낮은 주소 (0번 주소) 부터 채워넣는다.
만약 lb, lbu 명령어로 1번 주소의 값을 읽으면, 45를 읽어들인다.
반면 리틀 엔디안은 레지스터의 LSB 값 89를 낮은 주소 (0번 주소) 부터 채워넣는다.
따라서 리틀 엔디안은 메모리에 위와같이 LSB인 89를 낮은 주소 (0번 주소) 부터 채워넣는다.
만약 lb, lbu 명령어로 1번 주소의 값을 읽으면, 67을 읽어들인다.
우리가 설계하는 MIPS는 빅 엔디안 방식을 사용할 예정이다.
'CS > 컴퓨터 구조' 카테고리의 다른 글
[컴퓨터 구조] 7. MIPS 명령어 총 정리 (0) | 2024.04.16 |
---|---|
[컴퓨터 구조] 6. MIPS Branch Instructions (0) | 2024.04.15 |
[컴퓨터 구조] 4. MIPS Data Transfer Instructions (1) (0) | 2024.04.06 |
[컴퓨터 구조] 3. MIPS Arithmetic & Logical Instruction (0) | 2024.04.06 |
[컴퓨터 구조] 2. Clock & Verilog (0) | 2024.04.06 |