본문 바로가기

개념정리/System Hacking

2. x86-64 아키텍처

1. x86-64 아키텍처

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

 

- n 비트 아키텍처

n은 CPU가 한번에 처리할 수 있는 데이터의 크기이다. 64비트 아키텍처, 32비트 아키텍처에서는 CPU가 64비트, 32비트를 한번에 처리할 수 있다.

 

- 워드(WORD)

컴퓨터과학에서 CPU가 이해할 수 있는 데이터의 단위를 WORD라고 부른다. WORD의 크기는 CPU가 어떻게 설계됐느냐에 따라 달라진다. 32비트 아키텍처는 ALU는 32비트까지 계산할 수 있고 레지스터, 버스들의 대역폭이 32비트이다. 따라서 이들로 구성된 CPU는 32비트의 데이터까지만 처리할 수 있게 된다.

 

- 큰 WORD의 장점

현대의 PC는 대부분 64비트 아키텍처의 CPU를 사용하는데, 그 이유 중 하나는 32비트 아키텍처의 CPU가 제공할 수 있는 가상메모리의 크기가 작기 때문이다. 가상메모리는 CPU가 프로세스에게 제공하는 가상의 메모리 공간인데, 32비트 아키텍처에서는 4,294,967,296바이트(=4기가 바이트)가 최대로 제공 가능한 가상메모리의 크기이다. 반면 64비트 아키텍처에서는 이론상 16엑사 바이트(=16,777,216 테라바이트)의 가상메모리를 제공할 수 있다. 이는 웬만해서는 완전한 사용이 불가능할 정도로 큰 크기이기 때문에, 가용한 메모리 자원이 부족해서 소프트웨어의 최고 성능을 낼 수 없다거나 소프트웨어의 실행이 불가능한 상황은 거의 발생하지 않는다.

 

2. x86-64 아키텍처 레지스터

레지스터는 CPU가 데이터를 빠르게 저장하고 사용할 때 이용하는 보관소이며, 산술 연산에 필요한 데이터를 저장하거나 주소를 저장하고 참조하는 등 다양한 용도로 사용된다. x64 아키텍처에는 1)범용 레지스터(General Register), 2)세그먼트 레지스터(Segment Register), 3)명령어 포인터 레지스터(Instruction Pointer Register, IP), 4)플래그 레지스터(Flag Register)가 존재한다.

 

 

1) 범용 레지스터(General Register)

범용 레지스터는 주용도는 있으나, 그 외의 다양한 용도로 사용될 수 있는 레지스터이다. x86-64에서 각각의 범용 레지스터는 8바이트를 저장할 수 있으며, 부호 없는 정수를 기준으로 2^64 - 1까지의 수를 나타낼 수 있다. 자주 쓰이는 범용 레지스터들의 주용도는 밑에 표와 같다. 이 외에도 x64에는 r8, r9, … , r15까지의 범용 레지스터가 더 존재한다.

이름 주용도
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) 스택의 바닥을 가리키는 포인터

 

2) 세그먼트 레지스터(Segment Register)

x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재하며, 각 레지스터의 크기는 16비트이다. 세그먼트 레지스터는 x64로 아키텍처가 확장되면서 용도에 큰 변화가 생긴 레지스터이다. 현대의 x64에서 cs, ds, ss 레지스터는 코드 영역과 데이터, 스택 메모리 영역을 가리킬 때 사용되고, 나머지 레지스터는 운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작된 세그먼트 레지스터이다.

 

3) 명령어 포인터 레지스터(Instruction Pointer Register, IP)

프로그램은 일련의 기계어 코드들로 이루어져 있다. 이 중에서 CPU가 어느 부분의 코드를 실행할지 가리키는게 명령어 포인터 레지스터의 역할이다. x64 아키텍처의 명령어 레지스터는 rip이며, 크기는 8바이트입니다.

 

4) 플래그 레지스터(Flag Register)

플래그 레지스터는 프로세서의 현재 상태를 저장하고 있는 레지스터이다. x64 아키텍처에서는 RFLAGS라고 불리는 64비트 크기의 플래그 레지스터가 존재하며, 과거 16비트 플래그 레지스터가 확장된 것이다. 플래그 레지스터는 자신을 구성하는 여러 비트들로 CPU의 현재 상태를 표현한다. 주로 접하는 4가지 플래그는 밑에 표와 같다.

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

 

3. 레지스터 호환

 x86-64 아키텍처는 IA-32의 64비트 확장 아키텍처이며, 호환이 가능하다.  IA-32에서 CPU의 레지스터들은 32비트 크기를 가지며, 이들의 명칭은 각각 eax, ebx, ecx, edx, esi, edi, esp, ebp이다. 호환성을 위해 이 레지스터들은 x86-64에서도 그대로 사용이 가능하다. rax는 eax의 확장된 형태이며, eax는 확장된 rax 레지스터의 하위 32비트를 의미한다. 아래 그림은 rax, eax, ax, ah, al을 비교한 것이다.

 

레지스터 크기 비교