최규상 님의 KOCW 강의 "컴퓨터 구조"를 정리한 글입니다.
* David A. Patterson님과 John L. Hennessy 님의
"컴퓨터 구조 및 설계" 책을 교제로 한 강의입니다. (책의 내용은 포함되지 않았습니다)
1. Signed and Unsigned Numbers
Unsigned Binary Integers
2s-Complement Signed Integers
- LSB를 부호비트로 사용
2. Representing Instructions in the Computer
- 모든 기계어는 바이너리로 표현됨
MIPS Instructions
- MIPS의 워드는 32-bit
- 명령어가 32-bit 단위로 해석됨
MIPS R-Format Instructions
Field | 비트 크기 | 설명 |
op | 6bit | operation code (연산 코드) |
rs | 5bit | 첫 번째 소스 레지스터 번호 |
rt | 5bit | 두 번째 소스 레지스터 번호 |
rd | 5bit | 목적지 레지스터 번호 |
shamt | 5bit | shift amount (이동할 비트 수, 현재는 00000) |
funct | 6bit | function code (확장된 opcode) |
add $t0, $s1, $s2
special $s1 $s2 $t0 0 add
0 17 18 8 0 32
-> 0x02324020
- Hexadecimal (Base 16): 이해를 쉽게 하기 위해 16진수로 표기
MIPS I-format Instructions
- Immediate arithmetic and load/store
Field | 비트 크기 | 설명 |
op | 6bit | operation code (연산 코드) |
rs | 5bit | 첫 번째 소스 레지스터 번호 |
rt | 5bit | 두 번째 소스 레지스터 번호 |
constant/address | 16bit | 상수 값 또는 오프셋 |
Stored Program Computers
- Binary Compatibility는 Standard ISAs 여부에 결정됨
3. Logical Operations
연산 | 설명 |
shift left (sll) | 비트를 왼쪽으로 이동 |
shift right (srl) | 비트를 오른쪽으로 이동 |
bitwise and (and, andi) | 비트별 AND 연산 |
bitwise or (or, ori) | 비트별 OR 연산 |
bitwise not (nor) |
비트별 NOT 연산 (OR와 결합된 형태)
|
Shift Operations
- shamt: 얼마나 포지션이 시프트되었는지
4. Instructions for Making Decisions
Conditional Operations
- Branch to labeled instruction
if (rs==rt) L1;
if (rs!=rt) L1;
beq rs, rt, L1
bne rs, rt, L1
if (i==j) f = g+h;
else f = g-h;
bne $s3, $s4, Else
add $s0, $s1, $s2
j Exit
while (save[i] == k) i += 1;
Loop: sll $t1, $s3, 2
add $t1, $t1, $s6
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit:
Basic Blocks
- 조건문이나 반복문과 같은 브랜치가 ㅇ벗는 명령어들의 연속적인 시퀀스를 의미함
- 컴파일러는 Basic Block을 찾아 최적화를 수행하여 고성능을 얻을 수 있음
# 기본 블록 최적화 전
add $t0, $s1, $s2 # $t0 = $s1 + $s2
sub $t1, $s3, $s4 # $t1 = $s3 - $s4
mul $t2, $s5, $s6 # $t2 = $s5 * $s6
# 최적화 후 (불필요한 중복 계산 제거)
add $t0, $s1, $s2 # $t0 = $s1 + $s2
mul $t2, $s5, $s6 # $t2 = $s5 * $s6
4. Supporting Procedures in Computer Hardware
프로시저 실행 단계
- caller는 callee가 접근할 수 있는 곳에 argument들을 위치해둠
- caller는 callee에게 제어권을 넘김
- callee는 필요한 메모리 공간을 할당받음
- callee가 작업을 수행함
- callee가 다 작업을 수행하면, 리턴 값을 변수에 저장함
- callee는 caller에 제어권을 넘김
레지스터 사용
레지스터 | 이름 | 용도 |
$a0 - $a3 | 인자 레지스터 (Argument Registers) | 함수에 전달할 인자 저장 |
$v0 - $v1 | 반환 값 레지스터 (Value Registers) | 함수의 반환 값 저장 |
$t0 - $t9 | 임시 레지스터 (Temporary Registers) |
임시 데이터 저장 (함수 호출 시 보존되지 않음)
|
$s0 - $s7 | 저장 레지스터 (Saved Registers) |
값을 유지해야 하는 변수 저장 (함수 호출 시 보존됨)
|
$gp | 전역 포인터 (Global Pointer) |
정적 데이터 영역(global/static 변수) 가리킴
|
$sp | 스택 포인터 (Stack Pointer) | 현재 스택의 최상단 주소 가리킴 |
$fp | 프레임 포인터 (Frame Pointer) | 함수의 프레임(지역 변수 등) 관리 |
$ra | 반환 주소 (Return Address) | 함수 호출 후 반환할 주소 저장 |
프로시저 호출 명령어
명령어 | 설명 | 동작 |
jal ProcedureLabel | Jump and Link |
현재 주소(복귀 주소)를 $ra에 저장하고, ProcedureLabel로 점프
|
jr $ra | Jump Register |
$ra에 저장된 복귀 주소로 점프 (함수 반환)
|
example
int leaf_procedure_example(int g, int h, int i, int j)
{
int f;
f = (g + h) - (i + j);
return f;
}
leaf_procedure_example:
addi $sp, $sp, -4 // 스택에 공간 할당
sw $s0, 0($sp) // 이전 $s0값을 스택에 저장
add $t0, $a0, $a1
add $t1, $a2, $a3
sub $s0, $t0, $t1
add $v0, $s0, $zero
lw $s0, 0($sp) // 이전 $s0 값을 복원
addi $sp, $sp, 4 // 스택 포인터 복원
jr $ra // 반환: $ra에 저장된 주소로 점프
Local Data on the Stack
- 로컬 데이터는 callee에 의해 할당되며, 프로시저 프레임에 저장됨
Procedure frame (activation record)
- 프로시저 실행 시 생성되는 스택 프레임
- 함수가 실행될 때, 필요한 데이터를 저장
높은 주소 (High Address)
+---------------------------+ <- $sp (Stack Pointer, 현재 pop할 위치)
| Local Arrays & Structures | (함수 내부에서 사용하는 배열, 구조체)
+---------------------------+
| Saved Saved Registers | ($s0 ~ $s7, 보존해야 하는 레지스터)
+---------------------------+
| Saved Return Address | ($ra, 호출한 곳으로 복귀할 주소)
+---------------------------+
| Saved Argument Registers | ($a0 ~ $a3, 호출 시 전달된 인자)
+---------------------------+
| Previous Frame Pointer | (이전 함수의 $fp 값 저장)
+---------------------------+ <- $fp (Frame Pointer, 현재 함수의 시작)
낮은 주소 (Low Address)
항목 | 설명 | 관련 레지스터 |
Saved Argument Registers | 호출 시 전달된 인자를 저장 | $a0 ~ $a3 |
Saved Return Address | 함수 복귀 주소 저장 | $ra |
Saved Saved Registers | 함수 내에서 보존해야 하는 레지스터 | $s0 ~ $s7 |
Local Arrays and Structures | 함수 내부에서 사용하는 배열 및 구조체 | - |
Stack Pointer (스택 포인터) | Activation Record의 마지막 메모리 주소 (현재 스택 pop 위치) | $sp |
Frame Pointer (프레임 포인터) | Activation Record의 시작 메모리 주소 (현재 실행 중인 함수의 스택 프레임 시작 위치) | $fp |
Memory Layout
높은 주소 (High Address)
+-------------------------+
| Stack | <- $sp (Stack Pointer)
| | (함수 호출 시 Activation Record 할당)
| (아래 방향으로 성장 ↓) |
+-------------------------+
| Heap | <- malloc() 등의 동적 메모리 할당
| | (위 방향으로 성장 ↑)
+-------------------------+
| Static Data Segment | <- 글로벌 변수, static 변수
| (.data, .bss) |
+-------------------------+
| Text Segment | <- 프로그램 코드 (.text)
| |
+-------------------------+
| Reserved (OS) | <- 시스템, OS 영역
+-------------------------+
낮은 주소 (Low Address)
영역 | 설명 |
Reserved | 예약된 메모리 (시스템 용도) |
Text | 프로그램 코드 저장 (실행 코드 영역) |
Static Data |
전역 변수 및 정적 변수 (static 변수) 저장
|
Dynamic Data (Heap) | 동적 메모리 할당 (malloc, new 등) |
Stack |
함수 호출 시 Activation Record가 할당됨, 위에서 아래로 확장됨
|
- stackoverflow: heap에서 할당 시, stack 영역을 침범할 경우 나는 에러
5. Communicating with People
Character Data
Byte-encoded
- 각 문자를 8비트로 표현
- ASCII: 영어 및 기본 특수문자
- Latin-1(ISO-88590-1): 유럽 언어 지원
Unicode
- 전세계 문자 지원
- variable-length encodings: n비트로 한 문자 표현
- UTF-8: 1~4바이트 사용 (ASCII 호환)
- UTF-16: 2~4바이트 사용
Byte/Halfword Operations
명령어 | 설명 |
lb rt, offset(rs) |
메모리에서 1바이트(8비트) 값을 읽어와 rt에 저장 (sign-extended)
|
lbu rt, offset(rs) |
메모리에서 1바이트(8비트) 값을 읽어와 rt에 저장 (zero-extended)
|
sb rt, offset(rs) |
rt의 하위 8비트(오른쪽 바이트) 를 메모리에 저장
|
출처