폰 노이만 구조
하버드 구조
수정된 하버드 구조
x86, x86-64
ARM
MIPS
AVR
캐시 설계
파이프라이닝
슈퍼 스칼라
분기 예측
비순차적 명령어 처리
컴퓨터는 연산과 제어를 위해 CPU(중앙처리장치)를, 저장을 위해 memory(기억장치)를 사용. 장치간의 데이터나 제어 신호를 교환할 수 있도록 버스(bus)를 사용.
프로세스의 코드를 불러오고, 실행하고, 결과를 저장하는 일련의 모든 과정이 CPU에서 일어난다. cpu는 산술/논리 연산을 처리하는 ALU와 cpu를 제어하는 제어장치(Control Unit), 데이터를 저장하는 레지스터 등으로 구성된다.
기억장치는 주기억장치와 보조기억장치로 분류된다.
주기억장치: 프로그램 실행과정에서 필요한 데이터들을 임시로 저장하기 위해 사용. 대표적으로 RAM.
보조기억장치: 운영체제, 프로그램 등과 같은 데이터를 장기간 보관하고자 할 때 사용. 대표적으로 하드 드라이브(HDD), SSD.
컴퓨터 부품과 부품 사이 또는 컴퓨터와 컴퓨터 사이에 신호를 전송하는 통로.
대표적으로 데이터가 이동하는 데이터 버스(Data Bus), 주소를 지정하는 주소 버스(Address Bus), 읽기/쓰기를 제어하는 제어 버스(Control Bus)가 있다. 이 외에도 랜선이나 데이터 전송 목적의 소프트웨어, 프로토콜도 버스라고 불린다.
기억장치가 있는데 CPU안에 다른 저장장치가 필요한 이유
CPU의 연산속도는 주기억장치 및 보조기억장치와의 데이터 교환속도보다 압도적으로 빠르기 때문에 이들만 사용하면 병목현상 발생. 그래서 데이터 교환속도를 단축하기 위해 레지스터와 캐시라는 저장장치를 내부에 가진다.
CPU가 해석하는 명령어의 집합. 프로그램의 코드는 기계어로 작성되어 있는데, 프로그램을 실행하면 이 명령어들을 CPU가 읽고, 처리한다.
모든 컴퓨터가 동일한 수준의 연산 능력을 요구하지 않기 때문에 다양한 ISA가 개발되고 사용된다. 인텔의 x86-64는 고성능 프로세서를 설계하기 위해 사용되므로 데스크톱 또는 랩톱에 적합하다. 전력 소모와 발열이 적은 ARM이나 MIPS 또는 AVR의 프로세스는 임베디드 장비들에 사용된다.
그 중 x86-64 아키텍처를 살펴보려 한다.
x64 아키텍처는 인텔의 64비트 CPU 아키텍처이다. 대다수의 개인용 컴퓨터들이 인텔의 x64 CPU를 사용하고 있다.
64비트, 32비트는 CPU가 한번에 처리할 수 있는 데이터의 크기이다. CPU가 이해할 수 있는 데이터의 단위라는 의미에서 WORD라고 부른다. WORD의 크기는 CPU가 어떻게 설계되었느냐에 따라 달라진다. 예를 들면 32비트 아키텍처에서 ALU는 한 번에 32비트 크기의 값을 연산할 수 있고 레지스터 용량 및 각종 버스들의 대역폭이 32비트 크기를 가진다.
지금은 대부분 64비트 아키텍처의 CPU를 사용하는데 그 이유 중 하나는 32비트 아키텍처의 CPU가 제공할 수 있는 가상메모리 크기가 작기 때문이다.
32비트에서 최대로 제공 가능한 가상메모리 크기: 4,294,967,296바이트(=4기가 바이트)
64비트에서 최대로 제공 가능한 가상메모리 크기: 이론상 16엑사 바이트(=16,777,216 테라바이트)
<x86-64의 개발 역사>
1970년도 말부터 인텔은 IA-16과 IA-32 아키텍처로 CPU 시장을 선도. 이 때 개발한 CPU들을 8086, 80186, 80286 등으로 이름 붙였는데, 모두 86으로 끝났기 때문에 x86 CPU라고 불렸다.
그러다 64비트 아키텍처의 필요성을 느낀 인텔은 2001년 경에 64비트 아키텍처인 IA-64를 발표. 이를 이용하는 아이테니움 CPU를 출시. 그러나 성능상의 문제와 기존 x86 아키텍처와 호환되지 않는다는 단점이 있었다.
2003년에 AMD는 x86과 호환되는 64비트 아키텍처를 개발, 이를 탑재한 CPU를 출시. AMD는 이 아키텍처의 이름을 x86-64, 그리고 자사의 이름을 붙여 amd64라고 지었다.
자사의 기술을 응용한 x86-64가 시장에서 성공하는 것을 본 인텔은 이를 다시 차용해서 Intel64, IA-32e, EM64T라고 이름을 붙였다. 그래서 실제로 이들은 모두가 거의 같은 아키텍처이다.
결과적으로 이런 복잡한 개발과정을 거쳤기 때문에 x86-64는 여러 이름을 갖게 됐다.
CPU 내부의 저장장치로, CPU가 빠르게 접근하여 사용할 수 있다.
범용 레지스터
x86-64에서 각각의 범용 레지스터는 8바이트를 저장 가능.
대표적인 범용 레지스터
이름 | 주용도 |
---|---|
rax (accumulator register) | 함수의 반환 값 |
rbx (base register) | x64에서는 주된 용도 없음 |
rcx (counter register) | 반복문의 반복 횟수, 각종 연산의 시행 횟수 |
rdx (data register) | x64에서는 주된 용도 없음 |
rsi (source index) | 데이터를 옮길 때 원본을 가리키는 포인터 |
rdi (destination index) | 데이터를 옮길 때 목적지를 가리키는 포인터 |
rsp (stack pointer) | 사용중인 스택의 위치를 가리키는 포인터 |
rbp (stack base pointer) | 스택의 바닥을 가리키는 포인터 |
x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재하며, 각 레지스터의 크기는 16비트.
과거 IA-32, IA-16에서는 세그먼트 레지스터를 이용하여 사용 가능한 물리 메모리의 크기를 키우려고 했으나 x64에서는 사용가능한 주소 영역이 굉장히 넓기 때문에 그런 목적으로 세그먼트 레지스터를 사용하는 일은 거의 없다. 현재는 주로 메모리 보호를 위해 사용된다.
현대의 x64에서 cs, ds, ss 레지스터는 코드 영역과 데이터, 스택 메모리 영역을 가리킬 때 사용되고, 나머지 레지스터는 운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작된 세그먼트 레지스터이다.
CPU가 실행해야할 코드를 가리키는 레지스터.
x64 아키텍처의 명령어 레지스터는 rip, 크기는 8바이트.
프로세서의 현재 상태를 저장하고 있는 레지스터. 자신을 구성하는 여러 비트들로 CPU의 현재 상태를 표현한다.
대표적인 플래그 레지스터
플래그 | 의미 |
---|---|
CF(Carry Flag) | 부호 없는 수의 연산 결과가 비트의 범위를 넘을 경우 1 |
ZF(Zero Flag) | 연산의 결과가 0일 경우 1 |
SF(Sign Flag) | 연산의 결과가 음수일 경우 1 |
OF(Overflow Flag) | 부호 있는 수의 연산 결과가 비트 범위를 넘을 경우 1 |
x86-64 아키텍처는 IA-32의 64비트 확장 아키텍처이며, 호환이 가능.
32비트 레지스터: eax, ebx, ecx, edx, esi, edi, esp, ebp
이 레지스터들은 x86-64에서도 그대로 사용이 가능.
rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp가 이들의 확장된 형태이며 eax, ebx 등은 확장된 레지스터의 하위 32비트를 가리킨다.
ex) rax = 0x0123456789abcdef 이면
(1) eax = 0x89abcdef
(2) ax = 0xcdef
(3) ah = 0xcd
(4) al = 0xef