X86 Architecture
x64 아키텍처는 인텔 64비트 CPU 아키텍처입니다. 흔히 컴퓨터를 16bit 컴퓨터, 32bit 컴퓨터, 64bit 컴퓨터라고 부릅니다. 이것 전체를 다시말해 N비트 아키텍처로 부르겠습니다. 여기서 64, 32 같은 것들은 CPU가 한 번에 처리할 수 있는 데이터의 크기를 말합니다. 이를 컴퓨터가 이해할 수 있는 데이터의 단위라는 의미에서 WORD(워드)라고 부릅니다.
WORD가 크면 어떤 점이 유리할까요?
WORD가 크면 사용할 수 있는 가상메모리의 크기가 커지기 때문에 최근에는 64bit 컴퓨터를 주로 사용합니다. 32비트 아키텍처에서는 4기가 바이트가 최대로 가능한 가상메로리의 크기로 많은 메모리 자원을 소모하는 전문 소프트웨어나 고사양 게임 등을 할 때 부족할 수 있습니다. 최근에는 처음부터 64비트 기반으로 만들어진 프로그램도 많아 호환이 안되는 경우도 있습니다. 반면 64비트 아키텍처는 이론상 16엑사 바이트의 엄청나게 큰 메모리를 가지고 있습니다.
Intel x86 프로세서는 CISC 아키텍처를 사용합니다. 따라서 고사양 작업이 용이합니다.
x86 Registers
eax | Accumulator register | 누산기, 산술 연산에 사용(중간 결과를 저장해 놓음) |
ebx | Base register | 기본 레지스터, 데이터의 주소를 가리키는 포인터로 사용 |
ecx | Counter register | 카운터 레지스터, 시프트/회전 연산과 루프에서 사용 |
edx | Data register | 데이터 레지스터 - I/O 포트 엑세스 및 산술 함수에 사용 가능 |
esi | Source index register | 원본 인덱스 레지스터, 스트림 명령에서 소스를 가리키는 포인터로 사용 |
edi | Destination index register | 대상 인덱스 레지스터, 스트림 명령에서 도착점을 가리키는 포인터로 사용 |
ebp | Base pointer register | 기본 포인터 레지스터, 스택의 베이스를 가리키는 포인터로 사용 |
esp | Stack pointer | 스택 포인터, 스택의 최상단을 가리키는 포인터로 사용 |
모든 정수 레지스터는 32bit입니다. 그러나 대부분은 16비트 또는 8비트 하위 레지스터를 가지고 있습니다.
하위 레지스터
ax | Low 16 bits of eax | 낮은 16비트 |
bx | Low 16 bits of ebx | 낮은 16비트 |
cx | Low 16 bits of ecx | 낮은 16비트 |
dx | Low 16 bits of edx | 낮은 16비트 |
si | Low 16 bits of esi | 낮은 16비트 |
di | Low 16 bits of edi | 낮은 16비트 |
dp | Low 16 bits of ebp | 낮은 16비트 |
sp | Low 16 bits of esp | 낮은 16비트 |
al | Low 8 bits of eax | 낮은 8비트 |
ah | High 8 bits of ex | 높은 8비트 |
bl | Low 8 bits of ebx | 낮은 8비트 |
bh | High 8 bits of bx | 높은 8비트 |
cl | Low 8 bits of ecx | 낮은 8비트 |
ch | High 8 bits of cx | 높은 8비트 |
dl | Low 8 bits of edx | 낮은 8비트 |
dh | High 8 bits of dx | 높은 8비트 |
모두 정리하면 아래 표와 같습니다.
x64 Register
64비트 레지스터 | 하위 32비트 | 하위 16비트 | 하위 8비트 |
rax | eax | ax | al |
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | edx | si | sil |
rdi | esi | di | dil |
rbp | edi | dp | bpl |
rsp | ebp | sp | spl |
r8 | r8d | r8w | r8b |
r9 | r9d | r9w | r9b |
r10 | r10d | r10w | r10b |
r11 | r11d | r11w | r11b |
r12 | r12d | r12w | r12b |
r13 | r13d | r13w | r13b |
r14 | r14d | r14w | r14b |
r15 | r15d | r15w | r15b |
다음은 레지스터의 호환을 보겠습니다.
위의 그림과 같이 eax, ebx 등은 하위 32bit이고, ax, bx, cx 등은 eax, ebx, ecx 등의 하위 16bit입니다.
범용 레지스터(General Register)
범용 레지스터는 주용도는 있으나, 그 외의 다양한 용도로 사용될 수 있는 레지스터입니다. AMD64(x86-64) 기반 범용 레지스터를 알아보겠습니다.
64비트 레지스터 | Full Name | 주용도 |
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 | 스택의 바닥을 가리키는 포인터 |
추가적인 설명은 아래 글의 범용 레지스터 부분을 참조하세요.
2023.03.13 - [Security/System] - [003] x86 아키텍처의 어셈블리어 명령어
세그먼트 레지스터(Segment Register)
x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재합니다.
세그먼트 레지스터 | 용도 |
CS (Code Segment) | 코드 세그먼트의 시작 주소(코드를 가리킴) |
SS (Stack Segment) | 스택 세그먼트의 시작 주소(스택을 가리킴) |
DS (Data Segment) | 데이터 세그먼트의 시작주소(데이터를 가리킴) |
ES (Extra Segment) | 추가 세그먼트를 가리키는 시작 주소 - 추가적인 데이터를 가리킴 ('Extra'의 첫글자 'E') |
FS (F Segment) | 추가 세그먼트를 가리키는 시작 주소(여분) - 많은 추가적인 데이터를 가리킴 ('E' 다음은 'F') TEB(Thread Environment Block)의 주소를 지정하는데 사용 |
GS (G Segment) | 추가 세그먼트를 가리키는 시작 주소(여분) - 더 많은 추가적인 데이터를 가리킴 ('F' 다음은 'G') |
각 레지스터의 크기는 16비트이며, 세그먼트 레지스터는 x64로 아키텍처가 확장되면서 용도에 큰 변화가 생긴 레지스터입니다.
- 각 레지스터 크기: 16bit
- 코드, 데이터, 스택, 라이브러리 세그먼트로 구성
- 문자열 시작 주소를 저장하는데 사용
- 과거에는 세그먼트 레지스터로 사용 가능한 물 메모리의 크기를 키우려 했지만, x64에서는 거의 사용되지 않음
명령어 포인터 레지스터
명령어 포인터 레지스터는 CPU가 어느 부분의 코드를 실행할지 가리키는 역할을 합니다. x64 아키텍처에서 rip로 표기되며, 크기는 8바이트입니다.
플래그 레지스터(Flag Register)
플래그 레지스터는 프로세서의 현재 상태를 저장하고있는 레지스터입니다.
- 부호 없는 정수를 기준으로 2^64 - 1까지의 수를 나타낼 수 있음
- 접두사 r은 64bit, 접두사 e는 32bit 레지스터를 의미
Flag Code | Flag Name | 플레그 이름 | Flag Status | Description |
of | Overflow Flag | 오퍼블로 플래그 | nvov | 오버플로 없음 - 오버플로 |
df | Direction Flag | 방향 플레그 | updn | 위쪽 방향 - 방향 아래로 |
if | Interrupt Flag | 인터럽트 플레그 | diei | 인터럽트 사용 안 함 - 인터럽트 사용 |
sf | Sign Flag | 서명 플래그 | plng | 양수(또는 0) - 음수 |
zf | Zero Flag | 0 플래그 | nzzr | 0이 아닌 - 0 |
af | Auxiliary Carry Flag | 보조 캐리 플래그 | naac | 보조 캐리 없음 - 보조 캐리 |
pf | Parity Flag | 패리티 플래그 | pepo | 패리티 홀수 - 패리티도 |
cf | Carry Flag | 캐리 플래그 | nccy | 캐리 없음 - 캐리 |
tf | Trap Flag | 트랩 플래그 | - | tf가 0이면 명령 하나 실행 후, 예외 발생 디버거에서 단일 단계 추적하는데 사용 다른 애플리케이션에서 사용 금지 |
iopl | I/O Privilege Level | I/O 권한 수준 | - | I/O 권한 수준 0~3 사이의 값을 가진 2비트 정수 운영체제가 하드웨어를 엑세스 제어할 경우 사용 애플리케이션에서 사용 금지 |
주요한 플레그 레지스터만 살펴보면 다음과 같습니다.
Flag | Full name | 의미 |
CF | Carry Flag | 부호 없는 수의 연산 결과가 비트의 범위를 넘을 경우 설정 |
ZF | Zero Flag | 연산의 결과가 0일 경우 설정 |
SF | Sign Flag | 연산의 결과가 음수일 경우 설정 |
OF | Overflow Flag | 부호 있는 수의 연산 결과가 비트 범위를 넘을 경우 설정 |
다음과 같은 특징을 가지고 있습니다.
- 프로세서의 현재 상태를 저장하고 있는 레지스터
- x64 아키텍처에서는 RFLAGS라 불리는 64비트 플래그 레지스터가 존재
- CPU의 현재 상태 표현
- ex) a(3)-b(5)=음수(flag:SF) → (a<b)크기비교 가능
EFLAGS 레지스터
EFLAGS (Extended FLAGS) 레지스터는 CPU 동작 제어 또는 연산 결과 반영에 사용되는 레지스터다.
Flag Code | Flag Name | 플레그 이름 | 설명 | |
0 | CF | Carry Flag | 캐리 플래그 | 추가 캐리 또는 빼기 포함 작업을 할 때 확인 |
2 | PF | Parity Flag | 패리티 플래그 | 최하위 바이트의 설정 비트수가 2의 배수면 설정 |
4 | AF | Auxiliary Carry Flag | 보조 캐리 플래그 | 플래그를 조절, BCD(Binary Code Decimal) 숫자 산술 연산의 캐리 |
6 | ZF | Zero Flag | 제로 플래그 | 연산 결과가 영(0)이면 설정 |
7 | SF | Sign Flag | 서명 플래그 | 연산 결과가 음수일 경우 설정 |
8 | TF | Trap Flag | 트랩 플래그 | 단계별 디버깅 여부 설정 |
9 | IF | Interrupt Flag | 인터럽트 플레그 | 인터럽트가 활성화되면 설정 |
10 | DF | Direction Flag | 방향 플레그 | 문자열 작업은 포인터를 증가시키지 않고 감소시켜 메모리를 거꾸로 읽음 |
11 | OF | Overflow Flag | 오퍼블로 플래그 | 부호 있는 산술 연산으로 레지스터에 담기에는 너무 큰 값이 나오는 경우 설정 |
12-13 | IOPL | I/O Privilege Level | I/O 권한 수준 | 현재 프로세스의 Input/Output 권한 수준 |
14 | NT | Nested Task Flag | 중첩 테스크 플래그 | 인터럽트 복귀 명령 IRET의 실행 제어에 사용 |
16 | RF | Resume Flag | 재시작 플래그 | 디버깅 오류를 수락할지 여부를 제어하는데 사용 |
17 | VM | Virtual 8086 Mode Flag | 가상 8086 모드 마크 | 플래그 1: 프로세서가 가상 8086 모드의 작동상태 1이 아님: 프로세서가 일반 보호모드의 작동상태 |
18 | AC | Alignment Check | 얼라인먼트 체크 | 메모리 참조의 정렬 검사를 수행할지 여부 설정 |
19 | VIF | Virtual Interrupt Flag | 가상 인터럽트 플레그 | IF의 가상 이미지 |
20 | VIP | Virtual Interrupt Pending | 가상 인터럽트 보류 플래그 | 인터럽트가 보류 중인 경우 설정합니다.t |
21 | ID | Identity Register | 식별 플래그 | 설정할 수 있는 경우 CPUID 명령 지원 CPUID: x86 아키택처를 위한 프로세서 기계 명령어 |
출처
Microsoft x86, x64 프로세서 한국어, 영어 문서
- https://learn.microsoft.com/ko-kr/windows-hardware/drivers/debugger/the-x86-processor
- https://learn.microsoft.com/ko-kr/windows-hardware/drivers/debugger/x64-architecture
- https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/x86-architecture
- https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture
위키위키
- https://ko.wikibooks.org/wiki/X86_%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC/x86_%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98
- https://ko.wikipedia.org/wiki/CPUID
programmersought
드림핵
태그
#x64 #x86 #레지스터 #세그먼트 #아키텍처 #용어 #표 #플레그 #하위