이 글은 김영근 교수님의 컴퓨터 구조 강의를 듣고 정리한 내용입니다.
본문에서 얘기할 Instruction Set Architecture에 대해 이해하려면,
Programming Languages의 종류와 관계에 대해서 알아야 한다.
다양한 프로그래밍 언어가 존재하지만,
Hardward 관점에서 분류한다면 High-Level / Low-Level 2가지 종류로 나눌 수 있을 것이다.
아래와 같이 사용자가 High-Level Language를 이용해 Code를 작성하면,
Complier가 Low-Level Language로 변환하여 Machine이 이를 읽고 동작할 수 있게 해준다.
Assembly Language는, 실제 Machine이 해석할 수 있는 0,1 형태의 Code가 아니라,
사용자가 이해할 수 있는 형태로 Machine Code를 나타낸 형태이다.
단 Assembly Language와 High-Level Language의 차이점은,
Assembly Language는 Machine Code와 1:1 매칭이 되지만 High-Level Language는 그렇지 않다.
Machine Language는, 실제 Machine이 해석할 수 있는 0,1 형태의 Machine Code를 의미하며
Machine(Hardward)가 해당 Code를 직접 읽고 동작을 수행한다.
가상의 Assembly/Machine Code로 예를 들자면,
아래와 같이 Assembly Code는 우리가 이해할 수 있는 형태이고, Machine Code는 0,1 형태이다.
위의 그림에서 Complier가 High-Level Lang'를 Low-Level Lang'으로 변환해주는 역할을 했다.
그럼 Complier는 CPU의 동작들과 이를 수행하기 위한 Low-Level Lang'를 포함하고 있는걸까?
정확히 말하자면, 그렇지 않다.
해당 정보는 Instruction Set Architecture(이하 ISA)에 포함되어 있고,
Complier는 ISA로부터 해당 정보를 참조하여 작성 된 High-Level Lang'에 맞게끔
Low-Level Lang'의 순서를 결정한다고 생각하면 된다.
이러한 기능을 가진 ISA는 Hardware ↔︎ Software 사이의 Interface라고 말한다.
(아래의 연두색 부분이 Hardware, 하늘색 부분이 Software이다.)
ISA는 다음과 같은 정보를 제공함으로써 Software에서 Hardware를 제어할 수 있도록 해준다.
1️⃣ CPU 동작별 Machine Code Instruction
2️⃣ CPU 동작별 Assembly Code Instruction
3️⃣ Machine Code Instruction ↔︎ Assembly Code Instruction Mapping
ISA를 구성하고 있는 Instruction(명령어)에 대해서 더 자세히 살펴보자.
우리는 CPU를 통해 하고자 하는 작업은 주로 무언가를 계산하고 처리하는 연산 과정인데,
이러한 연산 과정에 필요한 모든 명령어가 정의되어 있고 ISA에 포함되어 있다고 생각하면 된다.
그럼 아래 그림을 통해서 실제 CPU의 연산 과정을 한번 살펴보자.
CPU에서 수행되는 모든 연산은 Register에 저장되어 있는 정보만을 가지고 이뤄지는데,
Register는 굉장히 빠르지만 비싸다는 문제가 있는 반면 Memory는 느리지만 싸다는 이점이 있다.
이런 특징 때문에 CPU의 Register 공간은 작고, Memory 공간은 더 크게 구성되어 있으며,
실제 연산 과정에서는 ① Memory의 데이터를 Register로 불러오고, ② 실제 연산을 수행한 뒤
③ 다시 Register 데이터를 Memory로 전송하는 과정이 반복된다.
따라서 Instruction은 연산 과정에서 이용되는 Register/Memory를 대상으로 하며
위에서 언급했던 모든 동작들을 포함해 제어(분기, 반복 등)에 관련된 Instruction이 존재한다.
(ISA Objects: Register & Memory / Operations: Instrunctions)
부가적으로, CPU 연산 시 필요한 데이터 이동 명령어 또한 비용이기 때문에
Complier는 Register 내에 데이터가 최대한 오래 머무를 수 있도록 하여
데이터의 이동에 필요한 비용을 최소화하도록 동작한다.
아래 예시와 같이 Register~L3 Cache 내에 데이터가 없는 경우,
Memory 단에 접근해야 하는데 여기에 125ns, 즉 Register 대비 125배 비용이 요구된다.