[Reversing] 3. 컴퓨터 아키텍쳐(Computer Architecture)

Wonder_Land🛕·2022년 8월 25일
0

[Reversing]

목록 보기
3/6
post-thumbnail

[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.


  1. 서론
  2. 컴퓨터 구조와 명령어 집합 구조
  3. x86-64 아키텍쳐
  4. Q&A
  5. 마치며

1. 서론

컴퓨터는 각자 다른 기능을 수행하는 여러 부품들로 구성되어 있습니다.

컴퓨터가 서로 다른 부품들이 모여 하나의 기계로서 작동할 수 있는 것은,
컴퓨터에 대한 기본적인 설계가 존재하기 때문입니다.

컴퓨터 과학에서는 이러한 설계를 '컴퓨터 구조(Computer Architecture)'라고 부릅니다.

컴퓨터 구조 중에서 특히 CPU가 사용하는 명령어와 관련된 설계를 '명령어 집합 구조(Instruction Set Architecture, ISA)'라고 하는데,
가장 널리 사용되는 ISA 중 하나가,
인텔의 'x86-64 아키텍쳐'입니다.


2. 컴퓨터 구조와 명령어 집합 구조

1) 컴퓨터 구조(Computer Architecture)

  • 컴퓨터 구조(Computer Architecture)
    : 컴퓨터가 효율적으로 작동할 수 있도록 하드웨어 및 소프트웨어의 기능을 고안하고, 이들을 구성하는 방법
    : 컴퓨터 기능 구조에 대한 설계, 명령어 집합 구조, 마이크로 아키텍쳐, 기타 하드웨어 및 컴퓨팅 방법에 대한 설계 등이 포함

컴퓨터 기능 구조에 대한 설계란,
컴퓨터가 연산을 효율적으로 하기 위해 어떤 기능들이 컴퓨터에 필요한지 분석하는 분야로,
대표적으로 폰 노이만 구조, 하버드 구조, 수정된 하버드 구조가 있습니다.

CPU 명령어에 대한 설계란,
'명령어 집합 구조(Instruction Set Architecture, ISA)'라고 불리며,
CPU가 처리해야 하는 명령어를 설계하는 분야입니다.
대표적으로 ARM, MIPS, AVR, 인텔의 x86 및 x86-64 등이 있습니다.

CPU의 하드웨어적 설계란,
'마이크로 아키텍쳐(Micro Architecture)'라고 불리며,
정의된 명령어 집합을 효율적으로 처리할 수 있도록, CPU 회로를 설계하는 분야입니다.

제가 참고한 강좌에서는,
컴퓨터 기능 구조로 폰 노이만 구조와,
명령어 집합 구조로 x86-64 아키텍쳐
에 대해 알아볼 것입니다.


2) 폰 노이만 구조

컴퓨터 과학자 중 한명인 폰 노이만은 컴퓨터에 '연산, 제어, 저장'의 세가지 핵심 기능이 필요하다고 생각했습니다.

근대의 컴퓨터는 연산과 제어를 위해 '중앙처리장치(Central Processing Unit, CPU)'를,
저장을 위해 '기억장치(Memory)'를 사용합니다.
그리고 장치간에 데이터나 제어 신호를 교환할 수 있는 전자 통로인 '버스(Bus)'를 사용합니다.

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

  • 중앙처리장치(Central Processing Unit, CPU)
    : 프로그램의 연산을 처리하고 시스템을 제어하는 컴퓨터의 두뇌
    : 프로세스의 코드를 불러오고, 실행하고, 결과를 저장하는 일련의 모든 과정이 일어나는 곳

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

(2) 기억장치(Memory)

  • 기억장치(Memory)
    : 컴퓨터가 동작하는데 필요한 여러 데이터를 저장하기 위해 사용되며, 용도에 따라 주기억장치와 보조기억장치로 구분

주기억장치는 프로그램 실행과정에서 필요한 데이터들을 임시로 저장하기 위해 사용되며,
대표적으로 램(Random-Acess Memory, RAM)이 있습니다.

보조기억장치는 운영 체제, 프로그램 등과 같은 데이터를 장기간 보관하고자 할 때 사용되며,
대표적으로 하드디스크(Hard Disk Drive, HDD), SSD(Solid State Drive)가 있습니다.

(3) 버스(Bus)

  • 버스(Bus)
    : 컴퓨터 부품과 부품 사이 또는 컴퓨터와 컴퓨터 사이에 신호를 전달하는 통로

데이터가 이동하는 데이터 버스(Data Bus),
주소를 지정하는 주소 버스(Address Bus),
읽기/쓰기를 제어하는 제어 버스(Control Bus)
등이 있습니다.


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

  • 명령어 집합 구조(Instruction Set Architecture, ISA)
    : CPU가 해석하는 명령어의 집합

프로그램은 기계어로 작성되어 있는데, 프로그램을 실행하면 이 명령어들을 CPU가 읽고, 처리합니다.

ISA는 정말 다양한 종류가 있습니다.
이렇게 다양한 ISA가 존재하는 이유는 모든 컴퓨터가 동일한 수준의 연산 능력을 요구하지 않으며, 컴퓨팅 환경도 다양하기 때문입니다.

예를 들어, 인텔의 x86-64는 고성능 프로세서를 설계하기 위해 사용됩니다.
따라서, 많은 전력을 소모하고 발열도 상대적으로 심합니다.
그러므로, 안정적으로 전력을 공급할 수 있고, 냉각장치를 구비하는데 공간상의 부담이 크지 않은 데스크톱이나 랩톱에 적합합니다.

제가 참고한 강의에서 x86-64아키텍처를 대상으로 하는 이유는,
인텔의 x86기반 CPU 점유율이 압도적이기 때문이라고 합니다.


3. x86-64 아키텍쳐

  • x86-64 아키텍쳐
    : 인텔의 64비트 CPU 아키텍쳐
    : 인텔의 32비트 CPU 아키텍쳐인 IA-32를 64비트로 확장시킨 것으로, 대다수의 개인용 컴퓨터들이 인텔의 x64 CPU를 사용

1) n 비트 아키텍쳐

위에서 언급한 '64비트 아키텍쳐', '32비트 아키텍쳐'에서 사용된 숫자들은,
CPU가 한번에 처리할 수 있는 데이터의 크기 입니다.

컴퓨터과학에서는 이를 'CPU가 이해할 수 있는 데이터의 단위'라는 의미에서 'WORD'라고 부릅니다.

WORD의 크기는 CPU가 설계된 방식에 따라 달라지는데,
32비트 아키텍쳐에서 ALU는 한 번에 32비트 크기의 값을 연산할 수 있으며,
레지스터의 용량 및 각종 버스들의 대역폭도 32비트 크기를 갖습니다.
따라서 해당 부품들로 이루어진 CPU는 설계 상 32비트 데이터까지만 처리할 수 있습니다.

현대의 PC는 대부분 64비트 아키텍쳐의 CPU를 사용합니다.
그 이유는 32비트 아키텍처의 CPU가 제공하는 가상 메모리의 크기가 작기 때문입니다.
가상 메모리는 CPU가 프로세스에게 제공하는 메모리 공간으로,
32비트 체제에서는 약 4기가가 최대로 제공됩니다.
일상적인 수준으로는 적합하지만, 고사양게임이나 전문 소프트웨어에는 부족할 수 있습니다.

하지만 64비트 체제에서는 이론 상 약 16엑사 크기를 제공할 수 있습니다.
이는 너무나도 큰 수치이기 때문에, 메모리 자원이 부족해서 발생할 수 있는 문제들은 발생하지 않습니다.


2) 레지스터(Register)

  • 레지스터(Register)
    : CPU 내부의 저장장치로, CPU가 빠르게 접근하여 사용할 수 있습니다.
    : 산술 연산에 필요한 데이터를 저장하거나, 주소를 저장하고 참조하는 등 다양한 용도로 사용

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

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

  • 범용 레지스터(General Register)
    : 주용도는 있으나, 그 외 임의의 용도로도 사용될 수 있는 레지스터
    : x86-64에서는 각각 8바이트를 저장할 수 있습니다.
이름주용도
rax (Accumulator register)함수의 반환값
rbx (Base register)x64에서는 주된 용도 없음
rcx (Counter register)반복문의 반복 횟수
각종 연산의 횟수
rdx (Data register)x64에서는 주된 용도 없음
rsi (Souce Index)데이터를 옮길 때 원본을 가리키는 포인터
rdi (Destination Index)데이터를 옮길 때 목적지를 가리키는 포인터
rsp (Stack Pointer)사용중인 스택의 위치를 가리키는 포인터
rbp (Base Pointer)스택의 바닥을 가리키는 포인터

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

x64 아키텍처에는 'cs, ss, ds, es, fs, gs' 총 6가지의 세그먼트 레지스터가 있으며,
각각의 크기는 16비트입니다.

cs, ds, ss 레지스터는 코드 영역과, 데이터, 스택 메모리 영역을 가리킬 때 사용되며,
나머지 레지스터는 운영체제 별로 용도를 결정할 수 있도록 범용적인 용도로 제작된 세그먼트 레지스터입니다.

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

  • 명령어 포인터 레지스터(Instruction Pointer Register, IP)
    : CPU가 다음으로 실행할 명령어의 주소값을 저장하는 레지스터
    : x64 아키텍처에서는 rip이며, 크기는 8바이트입니다.

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

  • 플래그 레지스터(Flag Register)
    : 프로세서의 현재 상태를 저장하고 있는 레지스터

x64 아키텍처에서는 'RFLAGS'라고 불리는 64비트 크기의 플래그 레지스터가 존재합니다.

깃발을 올리고, 내리는 행위로 신호를 전달하듯, 플래그 레지스터는 자신을 구성하는 여러 비트들로 CPU의 현재 상태를 표현합니다.

주로 접하는 플래그 비트는 다음과 같습니다.

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

(5) 레지스터 호환

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

IA-32에서 CPU의 레지스터들은 32비트의 크기를 가지며,
각각 eax, ebx, ecs, edx, esi, edi, esp, ebp였습니다.
호환성을 위해 x86-64에서도 그대로 사용가능합니다.

앞서 본 rax, rbx, rcx, rdx, rsi, rdi, exp, ebp가 확장된 형태이며,
e 접두사를 가진 레지스터(32비트)는 r 접두사를 가진 레지스터(64비트)의 하위 32비트를 가리킵니다.

또한, 과거의 16비트 아키텍처인 IA-16과의 호환성을 위해,
ax, bx, cs, dx, si, di, sp, bpe접두사를 가진 레지스터(32비트)의 하위 16비트를 가리킵니다.

그리고 이들의 상위 8비트는 ah, bh, ch, dh,
하위 8비트는 al, bl, cl, dl로 나뉠 수 있습니다.


4. Q&A

-


5. 마치며

오늘은 컴퓨터의 아키텍처에 대해 알아봤습니다.

리버싱을 공부하기 전 기본적인 컴퓨터 과학 지식인데요.
대학교에서 뭔 소린지 모르고 멍 때리면서 수업을 듣던 때가 기억이 나네요.

보안 공부를 하면서 여기 저기 삽질하면서 해당 내용을 여러 번 접하다 보니까 점점 익숙해지는 것 같습니다. 😉

나 자신 화이팅!!

[Reference] : 위 글은 다음 내용을 제가 공부한 후, 인용∙참고∙정리하여 만들어진 게시글입니다.

profile
아무것도 모르는 컴공 학생의 Wonder_Land

0개의 댓글