◼ 컴퓨터 구조를 이해하고 있다면 문제상황을 빠르게 이해할 수 있고, 문제 해결의 실마리를 다양하게 찾을 수 있다.
◼ 성능, 용량, 비용 문제는 프로그래밍 언어의 문법만 알아서 해결하기 어렵기 때문에, 컴퓨터 구조를 알아야 한다.
◼ 알아야 하는 컴퓨터 구조 지식
◼ 앞서 설명한 컴퓨터의 핵심 부품들은 모두 메인보드(마더보드)에 연결된다.
◼ 메인보드에 연결된 부품들은 버스라는 내부 통로를 통해 서로 정보를 주고받을 수 있다.
◼ 컴퓨터 내부에는 다양한 버스가 있는데 그 중 가장 중요한 버스는 시스템 버스이다.
◼ 시스템 버스는 제어 버스, 데이터 버스, 주소버스로 구성된다.
- 제어 버스: 제어 신호를 주고 받는 통로
- 데이터 버스: 명령어와 데이터를 주고 받는 통로
- 주소 버스: 주소를 주고 받는 통로
◼ 컴퓨터가 이해하는 가장 작은 정보 단위는 비트(bit)이다.
◼ 비트보다 한 단계 큰 단위로 바이트(byte)가 있다.
◼ 워드(word)란 CPU가 한 번에 처리할 수 있는 데이터 크기를 의미한다.
📌 이진법
📌 이진수의 음수 표현
◼ 2의 보수의 한계
📌 십육진법
십육진법임을 표현하기 위해 아래 첨자 (16)을 붙이거나 십육진수 앞에 0x를 붙인다.
십육진법을 사용하는 주된 이유 중 하나는 이진수와의 상호 변환이 쉽기 때문이다.
십육진수를 이진수로 변환하기
: 십육진수 한 글자를 4비트의 이진수로 간주
이진수를 십육진수로 변환하기
: 4비트의 이진수를 한 글자의 십육진수로 변환
◼ 문자집합 : 컴퓨터가 인식하고 표현할 수 있는 문자의 모음
◼ 인코딩 : 문자 집합에 있는 문자들을 컴퓨터가 이해할 수 있는 0과 1로 변환하는 과정
◼ 디코딩 : 0과 1로 표현된 문자 코드를 사람이 읽을 수 있는 문자로 변환하는 과정
📌아스키 코드
📌EUC-KR
📌유니코드와 UTF-8
📌 고급 언어
: 사람을 위한 언어
📌 저급 언어
: 컴퓨터를 위한 언어 (컴퓨터가 직접 이해하고 실행할 수 있는 언어)
: 저급 언어는 명령어로 이루어져 있다.
➡고급 언어로 작성된 소스 코드는 반드시 저급 언어(명령어)로 변환되어야 한다.
: 저급 언어의 종류에는 기계어와 어셈블리어로 두 종류가 있다.
◼ 기계어
: 0과 1의 명령어 비트로 이루어진 언어
◼ 어셈블리어
: 기계어를 읽기 편한 형태로 번역한 저급 언어
: 어셈블리어를 읽으면 컴퓨터 프로그램을 어떤 과정으로 실행하는 지, 어떤 절차로 작동하는지를 가장 근본적인 단계에서부터 하나하나 추적하고 관찰할 수 있다.
◼ 고급언어가 저급 언어로 변환하는 방식에는 컴파일 방식과 인터프리터 방식이 있다.
: 컴파일 방식으로 작동하는 프로그래밍 언어
: 컴파일러에 의해 소스 코드 전체가 저급 언어로 변환된다.
: 컴파일 도중 오류가 발생하면 전체가 컴파일 되지 않는다.
: 컴파일러를 통해 저급 언어로 변환된 코드를 목적 코드라고 한다.
: 인터프리터 방식으로 작동하는 프로그래밍 언어
: 인터프리터에 의해 소스 코드가 한 줄씩 실행된다.
: 소스 코드 전체를 저급 언어로 변환하지 않기 때문에 변환에 있어서 시간을 기다릴 필요가 없다.
: N번째 줄에 문제가 있더라도 N-1번째 줄까지는 올바르게 수행된다.
: 목적코드는 컴퓨터가 이해하고 실행할 수 있는 저급 언어인 반면, 인터프리터 언어는 소스 코드 마지막에 이를 때까지 한 줄씩 저급 언어로 해석하며 실행해야 하기 때문이다.
📌연산 코드 (연산자)
: 명령어가 수행할 연산
: 가장 기본적인 연산 코드 유형 네 가지
MOVE: 데이터를 옮겨라
STORE: 메모리에 저장하라
LOAD: 메모리에서 CPU로 데이터를 가져와라
PUSH: 스택에 제이터를 저장하라
POP: 스택의 최상단 데잍를 가져와라
ADD/SUBTRACT/MULTIPLY/DIVIDE: 덧셈/뺄셈/곱셈/나눗셈을 수행하라
INCREMENT/DECREMENT: 오퍼랜드에 1을 더하라/ 오퍼랜드에 1을 빼라
AND/OR/NOT: AND/OR/NOT 연산을 수행하라
COMPARE: 두 개의 숫자 또는 TRUE/FALSE 값을 비교하라
JUMP: 특정 주소로 실행 순서를 옮겨라
CONDITIONAL JUMP: 조건에 부합할 때 특정 주소로 실행 순서를 옮겨라
CALL: 되돌아올 주소를 저장한 채 특정 주소로 실행 순서를 옮겨라
RETURN: CALL을 호출할 떄 저장했던 주소로 돌아가라
READ: 특정 입출력 장치로부터 데이터를 읽어라
WRITE: 특정 입출력 장치로부터 데이터를 써라
START IO: 입출력 장치를 시작하라
TEST IO: 입출력 장치의 상태를 확인하라
📌오퍼랜드 (피연산자)
: 연산에 사용할 데이터, 연산에 사용할 데이터가 저장된 위치
: 오펀랜드 필드에는 숫자와 문자 등을 나타내는 데이터 또는 메모리나 레지스터 주소가 올 수 있다.
: 오퍼랜드는 명령어 안에 0~여러개 있을 수 있다.
- 0-주소 명령어: 오퍼랜드가 하나도 없는 명령어
- 1-주소 명령어: 오퍼랜드가 1개인 명령어
- 2-주소 명령어: 오퍼랜드가 2개인 명령어
- 3-주소 명령어: 오퍼랜드가 3개인 명령어
➡ 명령어 길이 때문이다.
: n비트로 구성된 명령어의 연산 코드 필드가 m비트라면 1-주소 명령어인 경우에 오퍼랜드 필드 길이는 (n-m)비트가 된다.
즉, 하나의 오퍼랜드 필드로 표현할 수 있는 정보의 가짓수가 2(n-m)개이다.
: 만약 오퍼랜드 필드에 메모리나 레지스터 주소가 담긴다면 표현할 수 있는 정보의 가짓수(데이터의 크기)는 하나의 메모리나 레지스터 주소에 저장할 수 있는 공간만큼 커진다.
◼ 유효 주소
📌주소 지정 방식
1️⃣ 즉시 주소 지정 방식(immediate addressing mode)
연산에 사용할 데이터를 오퍼랜드 필드에 직접 명시
장점: 이하 주소 지정 방식들보다 빠름
단점: 표현할 수 있는 데이터의 크기가 작음
2️⃣ 직접 주소 지정 방식(direct addressing mode)
오퍼랜드 필드에 유효 주소를 직접적으로 명시
장점: 표현할 수 있는 데이터의 크기는 즉시 주소 지정 방식보다는 커짐
단점: 유효 주소를 표현할 수 있는 범위가 연산 코드의 비트 수만큼 줄어듦
3️⃣ 간접 주소 지정 방식(indirect addressing mode)
유효 주소의 주소를 오퍼랜드 필드에 명시
장점: 직접 주소 지정 방식보다 표현할 수 있는 유효 주소의 범위가 넓어짐
단점: 두 번의 메모리 접근이 필요하기 때문에 느림
4️⃣ 레지스터 주소 지정 방식(register addressing mode)
연산에 사용할 데이터를 저장한 레지스터를 오퍼랜드 필드에 명시
장점: 직접 주소 지정 방식보다 빠르게 데이터 접근 가능(CPU 외부에 있는 메모리에 접근하는 것보다 CPU 내부에 있는 레지스터에 접근하는 것이 빠르기 때문)
단점: 표현할 수 있는 레지스터 크기에 제한이 생길 수 있음
5️⃣ 레지스터 간접 주소 지정 방식(register indirect addressing mode)
연산에 사용할 데이터를 메모리에 저장하고, 그 주소를 저장한 레지스터를 오퍼랜드 필드에 명시
장점: 간접 주소 지정 방식보다 빠름(메모리 접근이 한 번이기 때문)