Section 01 : 컴퓨터 구조의 접근 방법
- 컴퓨터 구조에 대한 보다 근본적인 이해는 이후에 공부할 프로세스와 쓰레드 이해하는데 큰 도움.
- 컴퓨터 구조를 디자인한다는 관점에서 접근해서 공부할것.
컴퓨터 디자인하자
- 핵심적인 CPU 기능들과 그들이 상호작용하는 방식을 간단하게 소개합니다.
- CPU 전부를 논리-게이트(Logic Gata) 단위로 디자인하자는 것은 아니다.
- 레지스터만을 디자인 요소로 삼을것.
- CPU의 특성을 알 필요가 있는 시스템 프로그래머 입장에서 CPU를 보는 관점 대부분이 레지스터에 집중된다.
레지스터를 디자인하자
- 레지스터를 디자인하는데 중요한 요소
- 레지스터를 몇 비트로 구성할 것인가?
- 64비트 컴터를 사용하지만 공부할때는 부담되서 16비트로 공부할것.
- 몇 개 정도로 레지스터를 구성할 것인가?
- 레지스터 각각을 무슨 용도로 사용할 것인가?

- 레지스터 이름 r0 ~ r7
- r4(ir),r5(sp),r6(lr),r7(pc)
- ir(instruction register)
- sp(stack pointer)
- lr(link register)
- pc(program counter)
- ARM 코어를 참조한 것.
- 다른 어느 CPU 보다 하드웨어 구성과 명령어 구조가 간단하다.
- 전력소비가 아주 적어서 핸드폰에 매우 적합한 코어다.
명령어 구조 및 명령어를 디자인하자
- "레지스터를 디자인하였으니, 이를 바탕으로 명령어를 디자인할 차례다."
- 레지스터와 명령어의 상관 관계가 주목해야한다.
- CPU 구성형태(레지스터 구성형태)에 따라서 명령어 구조가 달라진다.
- CPU가 달라지면 이에 따른 명령어 구조가 달라지기 때문에, 어셈블리 언어로 구현된 프로그램은 구조가 다른 CPU로 이식이 불가능하다.
- 명령어 기본 구조 디자인 시작
- 16비트로 레지스터 크기를 결정했으므로 명령어 길이도 16비트로 구성하는게 좋다.
- 16비트의 활용 방안.
- 쉽게 생각하면: 명령어의 총 개수는 2^16승 해당하는 65536개가 될것이다. 그런데 좀 많다.. 이보다 더 비효율적일수도 없다.
- C/C++ 언어도 연산자를 포함하는 키워드 개수가 100개를 넘지 않는다.
- "레지스터 r1에 있는 값과 숫자 7을 더해서 레지스터 r2에 저장하라"
- 덧셈 연산을 필요한 것.
- 1.덧셈 대상이 되는 피연산자 둘(r1과 숫자 7)에
- 연산결과 저장을 위한 피연산자 하나(r2)가 필요하다.
- 이 모두를 16비트에 담으면 아주 효율적.
- "덧셈", "레지스터 r1", "레지스터 r2", "숫자 7"
- 하나에 명령어에 답으면 된다.

- Add연산자 뒤에는 세 개의 비트에는 연산결과만을 저장할 저장소 정보를 둘 것.
- 이곳에는 항상 연산결과를 저장할 레지스터 정보만 올수 있도록 제한할것.
- 세 비트만 할당한 이유는 레지스터의 총 8개 이므로 충분함.
- 그 뒤를 잇는 네개의 비트와 또 그뒤를 잇는 네개의 비트에는 레지스터 정보나 숫자가 올 수 있도록 디자인 할 것.
- 레지스터 정보가 온다면 레지스터 안에 저장된 데이터를 참조하겠다는 의미로 해석.
- 젤 앞에 2개의 비트는 지금 용도 결정 x 00으로만 채워둘것.
- 연산에 대한 정보를 나타내는 데 비트 수 3개를 할당했다.
- 연산자는 총 8개를 넘지 못한다.

- 그중 4개는 사칙연산 우로 채워넣었다.

- 덧셈 연산자 2진코드 채워넣었다.

- 각각의 레지스터의 2진 코드

- r2의 정보를 추가로 채운것.
- 연산 대상이 되는 두개의 피연산자는 숫자가 될수도 있고 레지스터가 될 수도 있당.
- 저장된 데이터가 숫자인지 레지스터 정보를 표현하는것인지 구분할게 필요하다.
- 문제 해결법: 하나의 비트를 희생함.
- 네 개의 비트중 가장 앞이 1이면 레지스터 정보
- 0이면 숫자 정보

- 제약사항
- 피연산자가 표현할 수 잇는 숫자가 8개 밖에 되지않음.
- 현존하는 대부분의 CPU에도 이와 유사한 형태의 제약사항이 실제로 존재함.
- 어셈블리 언어 기반의 프로그램 구현
- 어셈블러에 의한 바이너리 코드생성
- 저 명령은 컨트롤 유닛으로 전달되어 의미 해석되면 컨트롤 유닛은 CPU의 각 모듈에 명령을 내리게 된다.

- 명령어가 ir(Instruction Register)에 저장됨을 알수 있다.
- ir은 다음 번에 실행하게 될 명령어를 미리 가져다 놓는 용도로 사용된다.
- 지금 구성하는 명령어의 형태에 따라서 컨트롤 유닛의 구조가 결정된다.
- 컨트롤 유닛은 명령어 해석하는 역할 따라서 명령어 구성 및 해석방법을 정확히 알아야 해석 가능하다
- 명령어의 형태에 따라서 컨트롤 유닛의 논리회로가 디자인 된다.
"첫 번쨰 피연산자 위치에는 레지스터 이름이 와야한다." 약속한 이유?
- 이 문장은 (사칙)연산 결과는 일단 레지스터에 저장되어야 한다는 제약사항이 있음을 말해준다.
- 실제 CPU 어셈블리 프로그래밍하다보면 명령어를 구성하는 과정에서 몇몇 제약사항이 존재한다.
"왜 연산결과는 레지스터에만 저장되도록 제한하는지? 메인메모리에 직접 저장할 수 있도록, 피연산자로 메모리 주소가 오게끔 디자인할수도있지않나?"
- 디자인은 가능하다
- 그러나 명령어 구조가 복잡해지고 이에 따라 하드웨어 구성도 복잡해진다.
- 명령어를 처리하는데 걸리는 시간도 명령어 종류에 따라 다양해진다
- 명령어 종류에 따라 처리되는 시간이 다양해지는것은 단점
중요한 사실: 제약사항들은 CPU의 종합적 측면(성능, 비용 등)이 고려되는 가운데서 등장하게 된다. 떄문에 우리는 이러한 제약사항을 지켜야 한다.
RISC vs CISC
- CISC 장점
- 명령어 종류가 많다(다양한 조합이 가능)
- 프로그램을 구현하는데 잇어서 편리함 제공(수십줄 -> 단한줄 구현가능)
- 필요에 따라 명령어 길이도 유동적이기 떄문에 메모리 효율적으로 사용가능.
- CISC 단점
- 보다 높은 성능의 CPU를 디자인하기 위해서는 보다 단순한 CPU구조가 필요
- RISC 장점
- 명령어 수가 적다
- 명령어 크기 일정함
- 높은 성능을 낸다.
- 성능이 높은 이유
- 초당 클럭 수를 높이는 것도 성능을 향상시키는 일이지만 이보다 더 중요한것은 클럭당 처리할 수 있는 명령어의 개수다.
- RISC는 명령어 길이가 동일하고 명령어를 처리하는 과정이 일정하기 떄문에 클럭당 둘 이상의 명령어 처리가 가능하다(가장 큰 장점)
1차 23.12.27
2차 23.12.28
3차 23.12.29
4차 24.01.02
5차 24.01.03
6차 24.01.04
7차 24.01.05