[System] 80x86 시스템 CPU 구조와 레지스터

 

시스템 해킹


(1) 80x86 시스템 CPU 구조와 레지스터

1-1. 80x86 시스템

  • 8086/8088 시스템은 XT라고 칭했던 인텔 CPU의 IBM PC 중 아주 초기 보급형 모델

  • 그러다 AT라는 80286 시스템 발표, 이후부터 익숙한 이름의 모델이 등장

  • 바로 80을 떼고 80386을 386, 80486을 486으로 칭했던 시스템들이며 80x86은 이런 시스템을 통칭하는 말

[그림 1] 인텔 CPU 모델별 관련 정보

 

1-2. 80x86 시스템 CPU 구조

 

[그림 2] 80x86 시스템 구조

 

1-2-1. 연산 장치

  • 연산 장치(ALU)는 CPU(중앙 처리 장치) 핵심 부분 중 하나이며, 산술과 논리 연산을 수행하는 연산 회로 집합으로 구성

구성 요소 기능
내부 장치 가산기(Adder) 덧셈 연산 수행
보수기(Complementer) 뺄셈 연산 수행, 1의 보수나 2의 보수 방식 이용
시프터(Shifter) 비트를 오른쪽 / 왼쪽으로 이동하여 나눗셈, 곱셈 연산 수행
관련 레지스터 누산기(Accumulator) 연산의 중간 결과 저장

데이터 레지스터

(Data Register)

연산에 사용할 데이터 저장

          상태 레지스터           

(Status Register)

연산 실행 결과로 나타나는 양수나 음수, 자리 올림, 오버플로 상태 기억

 

1-2-2. 제어 장치

  • 제어 장치(CU)는 입출력, 기억 장치, 연산 장치를 제어하고 감시

  • 주기억 장치에 저장된 명령을 차례로 해독 > 연산 장치로 보내 처리하도록 지시

구성 요소 기능
내부 장치

명령 해독기

(Instruction Decoder)

명령 레지스터에 있는 명령 해독 > 부호기로 전송
부호기(Decoder) 명령 해독기가 전송한 명령 > 신호로 만들어 각 장치로 전송
주소 해독기(Address Decoder)

명령 레지스터에 있는 주소 해독 > 메모리 실제 주소로 변환

>  데이터 레지스터에 저장

관련 레지스터

프로그램 카운터

(Program Counter)

다음에 실행할 명령 주소를 저장

명령 레지스터

(Instruction Register)

현재 실행 중인 명령을 저장

메모리 주소 레지스터

(Memory Address Register)

주기억장치의 번지 저장

메모리 버퍼 레지스터

(Memory Buffer Register)

메모리 주소 레지스터에 저장된 주소 실제 내용 저장

 

1-3. 레지스터

  • 처리 중인 데이터나 처리 결과를 임시 보관하는 CPU 안의 기억장치

  • 대개 연산 장치나 제어 장치에 함께 포함

 

1-3-1. 레지스터 종류 & 기능

  • 사람이 일상 생활에서 메모하는 것처럼, 프로그램도 메모를 하는 데 이때 메모지 역할을 하는 것

  • 프로그램이 사용하는 메모지 종류와 내용을 알면 프로그램 동작 원리 이해에 도움

 

1-3-2. 범용 레지스터

범주 80386 레지스터 이름 비트 용도

범용 레지스터

(General Register)

EAX 누산기(Accumulator) 32

주로 산술 연산에 사용

(함수 결과 값 저장)

EBX

베이스 레지스터

(Base Register)

32

특정 주소 저장

(주소 지정 확대하는 인덱스로 사용)

ECX

카운트 레지스터

(Count Register)

32

반복적 실행되는 특정 명령에 사용

(루프 반복 횟수 & 좌우 방향 시프트 비트 수 기억)

EDX

데이터 레지스터

(Data Register)

32 일반 자료 저장(입출력 동작에 사용)

 

  • 연산 장치가 수행한 계산 결과의 임시 저장, 산술 및 논리 연산, 주소 색인 등 여러 목적으로 사용

  • 80386 CPU에서 사용하는 범용 레지스터는 EAX, EBX, ECX, EDX 등이 있음 

[그림 3] 범용 레지스터 종류 & 구분

 

  • 앞의 E는 '확장된'을 의미하며, 32비트 레지스터

  • 이 레지스터의 오른쪽 16비트를 각각 AX, BX, CX, DX라고 하며, 다시 둘로 나뉨

  • 예를 들어, AX는 왼쪽 8비트 상위 부분을 AH, 오른쪽 8비트 부분을 AL이라 함

 

EAX 레지스터

  • 누산기인 EAX 레지스터는 입출력과 대부분의 산술 연산에서 사용 (예 : 곱셈, 나눗셈, 변환 명령은 EAX 사용)

  • 사용 시에 더 효율적인 기계 코드를 생성하는 명령도 있으며, Win32 API 함수들은 모두 리턴 값을 EAX에 저장한 후에 리턴

 

EBX 레지스터

  • DS 세그먼트의 포인터를 주로 저장하며, ESI나 EDI와 결합하여 인덱스에 사용

  • BX는 메모리 주소 지정을 확장하기 위한 인덱스로 사용할 수 있는 유일한 범용 레지스터

 

ECX 레지스터

  • 루프가 반복되는 횟수를 제어하는 값, 왼쪽이나 오른쪽으로 이동되는 비트 수 등을 포함할 수 있음

 

EDX 레지스터

  • 입출력 연산에 사용하며, 큰 수의 곱셈과 나눗셈 연산에서 EAX와 함께 사용

 

 

1-3-3. 세그먼트 레지스터

범주 80386 레지스터 이름 비트 용도

세그먼트  레지스터

(Segment Register)

CS

코드 세그먼트 레지스터

(Code Segment Register)

16

실행할 기계 명령어가 저장된 메모리   주소 지정

DS

데이터 세그먼트 레지스터

(Data Segment Register)

16

프로그램에서 정의된 데이터, 상수,     작업 영역

메모리 주소 지정

SS

스택 세그먼트 레지스터

(Stack Segment Register)

16

프로그램 스택 세그먼트 시작 주소 저장

메모리 상에 스택 구현을 가능하게 함

ES, FS, GS

엑스트라 세그먼트 레지스터

(Extra Segment Register)

16 문자 연산과 추가 메모리를 지정하는 데 사용하는 여분의 레지스터

 

  • 세그먼트는 프로그램에 정의한 메모리 상의 특정 영역 (코드, 데이터, 스택 등을 포함)

  • 세그먼트는 메모리 대부분에 위치 가능, 실제 모드에서는 최대 64KB 크기까지 가능

  • 각 세그먼트의 주소를 지정하고, 특히 PC 계열에 사용하는 인텔 프로세서는 자신의 주소 지정 기능을 제공

  • 기본으로 CS, DS, SS 등 레지스터 세 개를 사용하며, ES나 FS, GS 레지스터는 여분으로 프로그램 크기나 필요에 따라 사용 가능

 

[그림 4] 세그먼트 레지스터 & 세그먼트 맵핑

 

CS 레지스터

  • 코드 세그먼트는 실행될 기계 명령을 포함

  • 코드 세그먼트의 시작 주소를 가리키며, 일반 프로그래밍에서는 이 레지스터를 직접 참조할 필요 X

 

DS 레지스터

  • 데이터 세그먼트는 프로그램에 정의된 데이터, 상수, 작업 영역을 포함

  • 데이터 세그먼트의 시작 주소를 가리키며, 프로그램은 참조하려는 데이터의 오프셋을 DS 레지스터에 저장된 주소 값에 더해 데이터 세그먼트 안의 데이터를 참조

 

SS 레지스터

  • 스택 세그먼트는 프로그램 실행 시, 실행 과정에서 필요 데이터나 연산 결과 등을 임시로 저장 / 삭제하는 목적 사용

  • 스택 세그먼트의 시작 주소를 가리킴

 

ES / FS / GS 레지스터

  • ES 레지스터는 추가로 사용된 데이터 세그먼트 주소를 가리킴

  • 메모리 주소 지정을 다루는 문자 데이터 연산에 사용하는 데, 이때 EDI 레지스터와 함께 사용

  • FS와 GS 레지스터도 목적은 비슷, 실제로는 거의 사용 X

 

 

2-3-4. 포인터 레지스터

범주 80386 레지스터 이름 비트 용도

포인터 레지스터

(Pointer Register)

EBP

베이스 포인터

(Base Pointer)

32

SS 레지스터와 함께 사용

스택 안의 변수 값을 읽는 데 사용

ESP

스택 포인터

(Stack Pointer)

32

SS 레지스터와 함께 사용

스택 가장 끝 주소를 가리킴

EIP

명령 포인터

(Instruction Pointer)

32

다음 명령어 오프셋(상대 위치 주소)을 저장

CS 레지스터와 합쳐 다음에 수행할 명령 주소 형성

 

  • 프로그램 실행 과정에서 사용하는 주요 메모리 주소 값을 저장

 

EBP 레지스터

  • 스택 세그먼트에서 현재 호출해서 사용하는 함수의 시작 주소 값 저장

  • 함수로 전달되는 지역 변수 등을 참조할 때 기준이 됨

  • ESP 레지스터와 함께 써서 스택 프레임을 형성하기도 함

  • 스택 프레임 기법은 함수가 호출될 때 ESP를 EBP에 저장하고 있다가 (mov %esp, %ebp) 모든 루틴이 끝나고 함수를 리턴하면 ESP 값을 돌려주어 스택 형성에 문제가 생기지 않도록 함

  • 실제 메모리 상 주소를 참조할 때 SS 레지스터와 함께 사용

 

ESP 레지스터

  • 현재 스택 영역에서 가장 하위 주소를 저장

  • 스택은 높은 주소 > 낮은 주소로 이동하면서 데이터를 저장하므로, 스택이 확장되면 스택 포인터도 높은 주소에서 낮은 주소로 값 변경

  • EBP와 마찬가지로 실제 메모리 상 주소를 참조할 때 SS 레지스터와 함께 사용

 

EIP 레지스터

  • 다음에 실행될 명령의 오프셋을 포함

  • 현재 실행 중인 코드 세그먼트에 속한 현재 명령을 가리킴

  • 실제 메모리 상 주소를 참조할 때 CS 레지스터와 함께 사용

 

 

1-3-5. 인덱스 레지스터

범주 80386 레지스터 이름 비트 용도

인덱스 레지스터

(Index Register)

EDI

목적지 인덱스

(Destination Index)

32 목적지 주소 값 저장
ESI

출발지 인덱스

(Source Index)

32 출발지 주소 값 저장

 

  • 데이터를 복사할 때 출발지와 목적지 주소를 각각 가리키는 레지스터로 사용

  • EDI, ESI가 있으며 오른쪽 16비트를 각각 DI, SI라고 함

 

 

ESI & EDI 레지스터

  • 주로 메모리의 한 영역(Source)에서 다른 영역(Destination)으로 데이터를 연속적으로 복사할 때 사용

  • 예로 strcpy(Destination, Source) 함수는 Source의 문자열을 Destination으로 복사할 때 두 메모리 주소를 저장하는 데 ESI와 EDI 레지스터를 사용

 

 

1-3-6. 플래그 레지스터

범주 80386 레지스터 이름 비트 용도
플래그 레지스터 EFLAGS

플래그 레지스터

(Flag Register)

32 연산 결과 및 시스템 상태와 관련된 여러 플래그 값 저장

 

[그림 5] EFLAGS 레지스터의 플래그 맵핑

 

  • 크기가 32비트이며, 컴퓨터의 다양한 상태를 나타내는 비트를 포함

  • 상태 플래그, 제어 플래그, 시스템 플래그로 구성됨

  • 위 그림에서 각 비트는 1(Set), 0(Clear) 값을 가지며, 비교 연산과 산술 연산을 포함하는 많은 명령이 플래그 상태를 변화시키고, 어떤 명령은 다음 행동을 결정하려고 플래그 상태를 점검함

 

 

상태 플래그 (State Flag)

  • 상태 플래그(0, 2, 4, 6, 7, 11비트)는 산술 명령(ADD, SUB, MUL, DIV) 결과를 반영

  • CF(Carry Flag / 비트 0) : 산술 연산 결과로 자리 올림이나 자리 내림이 발생할 때 세트된다. (STC, CLC 같은 어셈블리어 명령으로 값 수정 가능)

  • ZF(Zero Flag / 비트 6) : 산술 연산 결과가 0이면 세트(1), 0 이외에는 클리어(0)

  • OF(Overflow Flag / 비트 11) : 부호가 있는 수의 오버플로가 발생하거나 MSB(Most Significant Bit)를 변경했을 때 세트(1)

  • PF(Parity Flag / 비트 2) : 산술 연산 결과가 짝수이면 세트(1)

  • AF(Adjust Flag / 비트 4) : 8비트 피연산자를 사용한 산술 연산에서 비트 3을 비트 4로 자리올림하면 세트(1)

  • SF(Sign Flag / 비트 7) : 산술 및 논리 연산 결과가 음수이면 세트(1) 

 

제어 플래그 (Control Flag)

  • 제어 플래그인 DF(Direction Flag / 비트 10)는 스트링 명령(MOVS, CMPS, SCAS, LODS, STOS)을 제어

  • DF가 1이면 스트링 명령은 자동 감소함(스트링을 높은 주소에서 낮은 주소로 처리)

  • DF가 0이면 스트링 명령은 자동 증가(스트링을 낮은 주소에서 높은 주소로 처리)

  • STD / CLD 명령은 각각 DF 플래그가 세트(1)되고 클리어(0)됨

 

시스템 플래그 (System Flag)

  • 운영체제나 장치 드라이버를 제어

  • TF(Trap Flag / 비트 8) : 디버깅 할 때 'Single Step Mode'를 활성화하면 세트되고, 비활성화하면 클리어

  • IF(Interupt enable Flag / 비트 9) : 프로세서의 인터럽트 처리 여부를 제어하며, IF가 세트되어 있으면 시스템의 인터럽트를 처리하고 클리어 되어 있으면 시스템 인터럽트 무시

  • IOPL(I/O Privilege Level / 비트 12, 13) : 현재 실행하는 프로그램이나 태스크의 입출력 특권 레벨을 지시하며, 현재 실행 중인 프로그램이나 태스크가 I/O 주소 공간에 접근하려면 CPL이 I/O 특권 레벨보다 낮거나 같아야 함

  • NT(Nested Task Flag / 비트 14) : 인터럽트하거나 호출된 태스크를 제어하며, 현재 태스크를 이전에 실행된 태스크와 연결했으면 세트되고, 연결하지 않으면 클리어

  • RF(Resume Flag / 비트 16) : 프로세서 디버그 예외 반응을 제어하며, 세트되어 있으면 디버그 오류를 무시하고 다음 명령어 수행

  • VM(Virtual 8086 Mode Flag /비트 17) : V86 모드를 활성화하면 세트, 사용하지 않고 보호 모드로 리턴 시 클리어

  • AC(Alignment Check /비트 18) : 메모리 참조 시에 정렬 기능을 활성화하면 세트

  • VIF(Virtual Interrupt Flag / 비트 19), VIP(Virtual Interrupt Pending / 비트 20) : 가상 모드 확장과 관련해 사용

  • ID(IDentification / 비트 21) : CPUID 명령의 지원 유무 결정


# Reference

 

https://www.hanbit.co.kr/store/books/look.php?p_code=B3283906872

+ Recent posts