본문 바로가기
문제 풀이/[DreamHack]

[DreamHack] SystemHacking Stage2 - Background: Computer Architecture

by 조랩 2022. 12. 19.

Lecture

 

컴퓨터 구조(Computer Architecture)

- 컴퓨터가 효율적으로 작동할 수 있도록 하드웨어 및 소프트웨어의 기능을 고안하고 구성하는 방법이다.

- 기능 구조에 대한 설계, 명령어 집합 구조, 마이크로 아키텍처, 기타 하드웨어 및 컴퓨팅 방법에 대한 설계 등이 포함된다.

 

기능 구조에 대한 설계

- 컴퓨터가 연산을 효율적으로 하기 위해 어떤 기능들이 컴퓨터에 필요한지 고민하고 설계하는 분야이다.

- 폰 노이만 구조, 하버드 구조, 수정된 하버드 구조가 있다.

 

명령어 집합구조(Instruction Set Architecture)

- CPU가 처리해야하는 명령어를 설계하는 분야이다.

- ARM, MIPS, AVR, Intel의 x86, x86-64등이 있다.

 

마이크로 아키텍처(Micro Architecture)

- 정의된 명령어 집합을 효율적으로 처리할 수 있도록, CPU의 회로를 설계하는 분야이다.

 

기능 구조의 설계 - 폰 노이만 구조
- 하버드 구조
- 수정된 하버드 구조
명령어 집합 구조 - x86, x86-64
- ARM
- MIPS
- AVR
마이크로 아키텍처 - 캐시 설계
- 파이프라이닝
- 슈퍼스칼라
- 분기 예측
- 비순차적 명령어 처리
하드웨어 및 컴퓨팅 방법론 - 직접 메모리 접근

 

폰 노이만 구조

- 초기 컴퓨터 과학자 폰 노이만: 음... 컴퓨터에 연산, 제어, 저장의 세 가지 핵심 기능이 필요할 것 같은데 ?!?!???

- 현대: 연산과 제어를 위한 중앙 처리 장치(Central Processing Unit, CPU), 저장을 위해 기억장치(Memory), 장치간 제어신호 교환을 위해 버스(Bus)를 사용한다.

 

중앙 처리 장치 (Central Processing Unit, CPU)

- 프로그램의 연산을 처리하고 시스템을 관리하는 컴퓨터의 두뇌이다.

- 프로세스의 코드를 불러오고, 실행하고, 결과를 저장하는 모든 과정이 여기에서 일어난다.

- CPU는 산술/논리 연산을 처리하는 산술 논리 장치(Arithmetic Logic Unit, ALU)와 CPU를 제어하는 장치(Control Unit), 그리고 CPU에 필요한 데이터를 저장하는 레지스터(Register)로 구성된다.

 

기억장치가 있는데 왜 CPU안에 레지스터가 필요한가?

- CPU의 연산 처리 속도가 기억장치와의 데이터 교환 속도보다 압도적으로 빠르기 때문에, 기억장치만을 사용한다면 병목 현상이 생길 수 있다.

- 따라서 CPU는 교환속도를 획기적으로 단축하기 위해서 레지스터와 캐시라는 저장장치를 갖게 된다.

 

기억장치 (Memory)

- 컴퓨터가 동작하는데 필요한 여러 데이터를 저장하기 위해 사용된다.

- 용도에 따라 주기억장치(프로그램 실행과정에서 필요한 데이터들을 임시로 저장함)보조기억장치(운영체제, 프로그램 등과 같은 데이터를 장기간 보관함)로 분류된다.

- 주기억장치에는 대표적으로 램(Random-Access Memory, RAM)이 있다.

- 보조기억장치에는 하드 드라이브(Hard Disk Drive, HDD), SSD(Solid State Drive)가 있다.

 

버스 (Bus)

- 컴퓨터 부품과 부품, 컴퓨터와 컴퓨터 사이에 신호를 전송하는 통로이다.

데이터 버스(Data Bus) 데이터가 이동한다.
주소 버스(Address Bus) 주소를 지정한다.
제어 버스(Control Bus) 읽기/쓰기를 제어한다.

- 랜선이나 데이터 전송 소프트웨어, 프로토콜 등도 버스라고 불린다.

 

명령어 집합 구조(Instruction Set Architecture, ISA)

- CPU가 해석하는 명령어의 집합을 말한다.

- ISA에는 IA-32, x86-64(x64), MIPS, AVR등이 다양하게 존재한다.

- 다양한 이유? 모든 컴퓨터가 동일한 수준의 연산 능력을 요구하지 않으며, 컴퓨팅 환경도 다양하기 때문!

- 인텔의 x86-64: 고성능 프로세서를 설계하기 위해 사용된다. (안정적으로 전력을 공급할 수 있고, 냉각 장치를 구비하는데 공간상의 부담이 크지 않은 데스크톱 또는 랩톱에 적합함)

- ARM, MIPS, AVR: 전력소모와 발열이 적은 임베디드 장비들을 설계하기 위해 사용된다.

 

x86-64 아키텍처

- 인텔의 64비트 CPU 아키텍처 이다.

- 인텔의 32비트 CPU 아키텍처인  IA-32를 64비트 환경에서 사용할 수 있도록 확장한것이다.

 

n비트 아키텍처

- 64와 32는 CPU가 한번에 처리할 수 있는 데이터의 크기이다.

- 이를 WORD라고 부르며 이는 CPU가 이해할 수 있는 데이터의 단위 라는 의미이다.

- WORD의 크기는 CPU가 어떻게 설계되느냐에 따라 달라진다.

- 예를 들어 32비트 아키텍처에서 ALU는 32비트까지 계산할 수 있고, 레지스터의 용량 및 각종 버스들의 대역폭이 32비트이다.

 

WORD가 크면 유리한 점

- 가상 메모리의 크기가 커지기 때문이다.

- 32비트 아키텍처의 경우 4,294,967,296바이트( = 4기가 바이트)가 최대로 제공 가능한 가상 메모리이다.

- 64비트 아키텍처의 경우 이론상 16엑사 바이트( = 16,777,216 테라 바이트)가 최대로 제공 가능한 가상 메모리이다. 따라서 가용한 메모리 자원이 부족해서 소프트웨어의 최고 성능을 낼 수 없다거나 소프트웨어의 실행이 불가능한 상황은 거의 없다.

 

x86-64의 여러 이름

- Intel64

- IA-32e

- EM64T

- amd64

- amd64라는 명칭을 자주 볼 수 있는데, x86-64랑 같은거라고 생각해도 된다.

 

x86-64 아키텍처: 레지스터

- 레지스터: CPU가 데이터를 빠르게 저장하고 사용할 때 이용하는 보관소. 산술 연산에 필요한 데이터를 저장하거나 주소를 저장하고 참조하는 등 다양한 용도로 사용된다.

- x64 아키텍처에는 범용 레지스터(General Register), 세그먼트 레지스터(Segment Register), 명령어 포인터 레지스터(Instruction Pointer Register, IP), 플래그 레지스터(Flag Register)가 존재한다.

 

범용 레지스터 (General Register)

- 주 용도가 있으나, 그 외의 다양한 용도로 사용될 수 있는 레지스터이다.

- x86-64에서 각각의 범용 레지스터는 8바이트를 저장할 수 있고, 부호 없는 정수를 기준으로 2^64 - 1까지의 수를 나타낼 수 있다.

이름 주용도
rax (accumulator register) 함수의 반환 값
rbx (base register) x64에서는 주된 용도 없음
rcx (counter register) 반복문의 반복 횟수, 각종 연산의 시행 횟수
rdx (data register) x64에서는 주된 용도 없음
rsi (source index) 데이터를 옮길 때 원본을 가리키는 포인터
sdi (destination index) 데이터를 옮길 때 목적지를 가리키는 포인터
rsp (stack pointer) 사용중인 스택의 위치를 가리키는 포인터
rbp (stack base pointer) 스택의 바닥을 가리키는 포인터

- 이 외에도 x64에는 r8 ~ r15까지의 범용 레지스터가 더 존재한다.

 

세그먼트 레지스터

- cs, ss, ds, es, fs, gs 총 6가지의 세그먼트 레지스터가 존재한다.

- 각 레지스터의 크기는 16비트이다.

- x64로 아키텍처가 확장되면서 용도에 큰 변화가 생긴 레지스터이다.

- 현대의 x64에서 cs, ds, ss 레지스터는 코드 영역과 데이터, 스택 메모리 영역을 가리킬 때 사용된다.

- es, fs, gs운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작되었다.

 

명령어 포인터 레지스터

- CPU가 어느 부분의 코드를 실행할지 가리키는 역할을 한다.

- x64 아키텍처의 명령어 레지스터는 rip이며, 8바이트 크기 이다.

 

플래그 레지스터

- 프로세서의 현재 상태를 저장하고 있는 레지스터이다.

- x64에서는 RFLAGS라고 불리며 64비트 크기이다.

- RFLAGS는 64비트 이기 때문에 64개의 플래그를 사용할 수 있지만, 실제로는 오른쪽으 20여개 정도의 비트만 사용한다. 그중에서도 주로 접하게 될 플래그들은 아래 표와 같다.

플래그 의미
CF (Carry Flag) 부호 없는 수의 연산 결과가 비트 범위를 넘을 경우 설정 된다.
ZF (Zero Flag) 연산의 결과가 0일 경우 설정 된다.
SF (Sign Flag) 연산의 결과가 음수일 경우 설정 된다.
OF (Overflow Flag) 부호 있는 수의 연산 결과가 비트 범위를 넘을 경우 설정 된다.

 

- 예를 들어, a = 3과 b = 5가 있을 때, a - b를 하면 연산의 결과가 음수이므로 SF를 설정한다. 그러면 CPU는 SF를 통해 a가 b보다 작았음을 알 수 있다.

출처 - https://learn.dreamhack.io/43#10

 

레지스터 호환

- x86-64아키텍처는 IA-32의 64비트 확장 아키텍처이며, 호환이 가능하다.

- IA-32의 CPU레지스터들은 eax, ebx, ecx, edx, esi, edi, esp, ebp이고 호환성을 위해서 이 레지스터들은 x86-64에서도 그대로 사용 가능하다.

- rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp가 이들의 확장된 형태이며, eax, ebx등은 확장된 레지스터의 하위 32비트를 가리킨다.

- 예를 들어, eax는 rax의 하위 32비트를 의미한다.

- 마찬가지로 IA-16과의 호환을 위해 ax, bx, cx, dx, si, di, sp, bp는 eax, ebx, ecx, edx, esi, edi, esp, ebp의 하위 16비트를 가르킨다.

- 또한 이들중 ax, bx, cx, dx는 다시 상위 8비트, 하위 8비트로 나뉘는데 각각 ah, al, bh, bl, ch, cl, dh, dl이다.


728x90