폰 노이만
초기 컴퓨터 과학자 중 한 명이다. 노이만은 컴퓨터에 연산, 제어, 저장의 세 가지 핵심 기능이 필요하다고 생각했다. 근대의 컴퓨터는 연산과 제어를 위한 중앙처리장치, 저장을 위한 기억 장치, 장치간에 데이터나 제어 신호를 교환할 수 있도록 버스라는 전자 통로를 사용한다.
중앙처리장치
CPU는 프로그램의 연산을 처리하고 시스템을 관리하는 컴퓨터의 두뇌이다.
기억장치
기억장치는 컴퓨터가 동작하는데 필요한 여러 데이터를 저장하기 위해 사용되며, 용도에 따라 주기억장치와 보조기억장치로 분류된다. 주기억장치로는 RAM이 있으며, 보조기억장치는 하드 드라이브(HDD), SSD가 있다.
버스
버스는 컴퓨터 부품과 부품 사이 또는 컴퓨터와 컴퓨터 사이에 신호를 전송하는 통로를 말한다.
명령어 집합 구조
CPU가 해석하는 명렁어의 집합을 의미한다. ISA는 IA-32, x86-64, MIPS, AVR등 다양하게 존재한다.
x86-64아키텍처
범용적이고 중립적으로 지칭된다. 대다수의 컴퓨터가 x86-64 아키텍처 기반의 CPU를 탑재한다, n비트 아키텍처는 CPU가 한번에 처리할 수 있는 데이터의 크기이다. 이를 CPU가 이해할 수 있는 데이터단위라는 의미에서 WORD라고 부른다. WORD가 크면 클수록 성능이 좋아진다.
레지스터
CPU가 데이터를 빠르게 저장하고 사용할 때 이용하는 보관소이다. 산술 연산에 필요한 데이터를 저장하거나 주소를 참조하는 등 다양한 용도로 사용된다.
범용 레지스터는 주용도에 있으나 다양한 용도로 사용될 수 있다. 8바이트를 저장할 수 있으며 정수 기준으로 2^(64)-1까지의 수를 나타낼 수 있다.
이름 | 주용도 |
rax(accumlator 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) | 스택의 바닥을 가리키는 포인 |
세그먼트 레지스터
x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터가 존재한다. 각 레지스터의 크기는 16비트이다.
명령어 포인터 레지스터
CPU가 어느 부분의 코드를 실행할지 가리키는 역할이다. x64아키텍처의 명령어 레지스터는 rip이며, 크기는 8바이트이
플래그 레지스터
프로세서의 현재 상태를 저장한다. x64아키텍처에는 RFLAGS라고 불리는 64비트 크기의 플래그 레지스터가 존재한다. RFLAGS는 64비트이므로 최대 64개의 플래그를 사용가능하지만 실제로는 20여개를 사용한다.
레지스터 호환
x86-64아키텍처는 IA-32의 64비트 확장 아키텍처며 호환이 가능하다. 명칭은 eax, ebx, ecx, edx, esi, edi, esp, ebp다
퀴즈
ZF는 연산결과가 0일 때 된다. 그러므로 rax와 rbx는 같다.
ax는 하위 16비트를 말한다.
eax는 하위 32비트를 말한다.
ah는 ax의 상위 8비트를 말한다.
al은 ax의 하위 8비트이다.
세그먼트
리눅스에서는 프로세스 메모리를 크게 5가지 세그먼트로 구분한다. 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트로 구분된다.
코드 세그먼트
실행 가능한 기계 코드가 위치하는 영역으로 텍스트 세그먼트라고도 불린다. 읽기 권환가 실행 권한이 부여된다.
데이터 세그먼트
컴파일 시점에 값이 정해진 전역 변수 및 전역 상수들이 위치한다.
BSS세그먼트
컴파일 시점에 값이 정해지지 않은 전역 변수가 위치한다.
스택 세그먼트
프로세스의 스택이 위치하는 영역이다.
힙 세그먼트
힙 데이터가 위치하는 세그먼트이다. 스택과 마찬가지로 실행 중 동적으로 할당될 수 있으며 리눅스에서 스택 세그먼트와 반대 방향으로 자란다.
임시변수이기에 스택 세그먼트이다.
foo(해당 코드에서 일종의 명령어라고 생각합니다)를 사용하는 것이기에 코드 세그먼트이다.
전역으로 선언 됐기 읽기 전용 데이터(rodata)가 된다
malloc을 사용한 동적 데이터 할당이기에 힙 세그먼트다.
변수에 데이터 값을 저장했으므로 데이터 세그먼트다.
변수 값 저장 전이기에 BSS세그먼트이다.
전역으로 선언했기 읽기 전용 데이터 세그먼트다.
#include <stdio.h>
int main(void) {
int a = 10, b, c = 24, d;
char e = 'a'; //문자 a가 저장된다
b = c; //b에 정수형 24가 저장된다
a--; //후위가감연산자이다. 특별한 식이 없으므로 1이 감소하여 9가 된다.
b = a*c; //9*24가 된다
printf("%d %d %d %d %c", a, b, c, d, e);
return 0;
}