1. 컴퓨터 구조(폰 노이만 구조)
컴퓨터에는 '연산, 제어, 저장'이라는 세 가지 핵심 기능이 필요하다.
중앙처리장치(CPU)🧠: 연산과 제어를 위해 사용되는 컴퓨터 장치. CPU의 장치 구성은 크게 세 가지로 구성 되어있다.
1) 산술논리장치(ALU): 산술/논리 연산을 처리한다.
2) 제어장치(Control Unit): CPU를 제어한다.
3) 레지스터(Register): CPU에 필요한 데이터를 저장한다.
기억장치💾: 컴퓨터가 동작하는 데 필요한 여러 데이터를 저장하기 위해 사용된다. 기억장치는 크게 주기억장치와 보조기억장치로 나뉜다.
1) 주기억장치(RAM): "프로그램 실행과정"에서 필요한 데이터들을 "임시로 저장"하기 위해 사용된다.
2. 보조기억장치(HDD or SSD): "프로그램 실행과 상관 없이" 데이터들을 "장시간 저장"하기 위해 사용된다.
Q. 기억장치가 존재하는데 레지스터는 왜 필요한 건가요?
A: CPU는 굉장히 빠른 속도로 연산을 처리하기 때문에, 이를 위해 데이터의 빠른 교환이 필요하다.
'CPU의 연산속도>>>>>기억장치와의 데이터 교환속도'이기 때문에 데이터를 읽어올 때마다 기억장치와 데이터 교환을 하게되면, CPU의 연산속도를 데이터 교환속도가 따라가지 못 해 '병목현상'이 발생한다.
이 문제를 해결하기 위해 CPU는 빠른 연산을 위해 자체적으로 데이터 저장 공간인 '레지스터'와 '캐시'를 갖고있다.
2. 아키텍처
아키텍처의 종류는 IA-32 , x86-64(x64), MIPS, AVR 등 다양하지만, dreamhack의 System Hacking 커리큘럼에서는 x86-64(x64) 아키텍처만을 다루기로 한다.
이렇게 다양한 아키텍처가 존재하는 이유는 '각 환경에 적합한 프로세서의 종류가 다르기 때문'이다.
2-1. n비트 아키텍처
‘64비트 아키텍처', '32비트 아키텍처’에서 64와 32는 CPU가 한번에 처리할 수 있는 데이터의 크기이다.
이 데이터의 크기를 'CPU가 이해할 수 있는 데이터의 단위'로서 WORD라고 부른다.
운영체제별 WORD의 명칭과 크기는
WORD == 16bit(2byte)
DWORD == 32bit(4byte)
QWORD == 64bit(8byte)
로서, 이는 CPU가 읽을 수 있는 데이터의 기본 단위이다.
예를 들자면) 32bit 운영체제에서는 char형으로 1byte 크기의 변수를 선언해도, CPU는 DWORD(4byte)크기 만큼의 공간을 할당해주고, 1byte는 char형 변수가 사용하고, 남은 3byte는 masking되어 임의의 값으로 채워진다.
3. x86-64 아키텍처: 레지스터
데이터의 중요한 보관소 역할을 하는 레지스터는 x64 아키텍처에서 크게
범용 레지스터(General Register)
세그먼트 레지스터(Segment Register)
명령어 포인터 레지스터(Instruction Pointer Register, IP)
플래그 레지스터(Flag Register)
로 나눠볼 수 있다.
3-1. 범용 레지스터(General Register)
주용도는 있으나, 그 외의 다양한 용도로 사용될 수 있는 레지스터입니다. 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) | 스택의 바닥을 가리키는 포인터 |
이 중 중요한 레지스터를 딱 세 개만 꼽아보라고 한다면, AX, SP, BP 레지스터를 꼽을 수 있겠다.
3-2. 세그먼트 레지스터(Segment Register)
x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재하며, 각 레지스터의 크기는 16비트이다.
현대의 x64에서 cs: 코드 영역을 가리킴
ds: 데이터 영역을 가리킴
ss: 스택 메모리 영역을 가리킴
세그먼트 레지스터는 위와 같이 사용되며, 나머지 세 개의 세그먼트 레지스터(es, fs, gs)는 운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작된 세그먼트 레지스터이다.
3-3. 명령어 포인터 레지스터(Instruction Pointer Register, IP)
CPU가 어느 부분의 코드를 실행할지 가리키는 레지스터이다.
x64 아키텍처에서의 명령어 레지스터는 rip이며, 크기는 8바이트이다.
3-4. 플래그 레지스터(Flag Register)
플래그 레지스터는 자신을 구성하는 여러 비트들로 CPU의 현재 상태를 표현합니다.
x64 아키텍처의 플래그 레지스터는 64비트 크기로, 64개의 상태를 나타낼 수 있지만 실제로는 그림에 나타나있는 20여개의 비트만을 사용한다.
이 중 주요 플래그 네 개를 꼽자면 다음과 같다.
플래그 의미
CF(Carry Flag) | 부호 없는 수의 연산 결과가 비트의 범위를 넘을 경우 설정 됩니다. |
ZF(Zero Flag) | 연산의 결과가 0일 경우 설정 됩니다. |
SF(Sign Flag) | 연산의 결과가 음수일 경우 설정 됩니다. |
OF(Overflow Flag) | 부호 있는 수의 연산 결과가 비트 범위를 넘을 경우 설정 됩니다. |
레지스터 호환
rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp 레지스터는 64비트 크기를 갖고있으며,
32bit 아키텍처와 16bit 아키텍처의 레지스터로도 그림과 같이 호환이 가능하다.
추가 설명) RAX를 예로 들어보자면, RAX는 64비트 크기의 레지스터이다.
EAX는 RAX의 하위 32비트를 가리키며
AX는 EAX or RAX의 하위 16비트를 가리킨다, AX는 다시 AH와 AL로 나뉘어
AH는 AX의 상위 8비트, AL은 AX의 하위 8비트를 가리킨다
'DreamHack: System Hacking > F Stage 2' 카테고리의 다른 글
Background: x86 Assembly Essential Part(2) 스택, 프로시저, 시스템 콜 (0) | 2023.03.31 |
---|---|
Background: x86 Assembly Essential Part(1) 어셈블리 명령어 (0) | 2023.03.31 |
Quiz: Linux Memory Layout (0) | 2023.03.31 |
Background: Linux Memory Layout (0) | 2023.03.31 |
Quiz: Computer Architecture (0) | 2023.03.31 |