피연산자 (Operands of Computer Hardware)
우선 알아둬야 할 것이, CPU에서 Memory로 접근하는 것보다 register로 접근하는 것이 훨씬 빠르다는 것을 알고 있어야 한다.
Register Operands
이전 글(Operation)에서 연산 instructions은 register operands를 사용했다. (memory가 아닌 register임에 주목하자)
register는 프로세서 내부적으로 관리하는 저장공간으로, 데이터를 담을 수 있는 가장 기본적인 단위이다. 현대 레지스터의 크기는 일반적으로 32bit이다. 0~31로 번호가 매겨져있다. 이 32bit의 data는 "word"라고 불려진다.
- $t0, $t1, $t2, ... ,$t9 는 임시 값들이다.
- $s0, $s1, $s2, ... ,$s7 은 변수를 저장한다.
- 32개 중 나머지는 차차 살펴볼 것이다.
레지스터의 개수를 32개로 제한한 것으로 설계 원칙 중 2번째를 알 수 있다.
Design Principle 2: Smaller is faster
적은 양의 register를 둠으로써 register에서 값을 빠르게 찾을 수 있다.
Register Operand의 예시를 보자. 이전 글의 예시와 같은 C code이다.
C code:
f = (g+h) - (i+j);
Compiled MIPS code:
add $t0, $s1, $2
add $t1, $s3, $4
sub $s0, $t0, $t1
MIPS의 32개의 registers는 위의 표에서 확인할 수 있다.
MIPS Memory operands
모든 데이터는 처음에 다 Memory에 있다. 연산을 하기 위해서는 데이터를 Memory로부터 가져와야 한다.
그래서 연산을 하는 것은
1. Memory에서 registers로 value를 Load.
2. 연산 수행.
3. registers에서 Memory로 result를 Store.
하는 것이다.
(참고)
컴퓨터 메모리에서는 메모리에 데이터를 저장할 때 Big Endian, Little Endian으로 표현할 수 있는데, 이 방식에 따라 값을 저장하는 순서가 다르다.
이번에도 C code를 MIPS code로 바꾸는 예시를 보자.
C code:
g = h + A[8];
(g는 $s1, h는 $s2, A의 시작주소는 $s3)
MIPS code:
lw $t0, 32($s3) // load word
add $s1, $s2, $t0
여기서 32는 offset이고, $s3는 base register인데,
$s3에서 32 만큼 떨어진 거리(주소) => A[8]을 의미한다.
A[0] = aX1000
A[1] = aX1004
...
A[8] = aX1032
store 예시
C code:
A[12] = h + A[8]
(h는 $s2, A의 시작주소는 $s3)
MIPS code:
lw $t0, 32($s3) // load word
add $t0, $s2, $t0
sw $t0, 48($s3) // store word
$s3에서 48 만큼 떨어진 위치는 A[12]이다. A[12]에 $t0 값을 store!
중간정리
연산과정
- 데이터는 Memory 안에 있다.
- Memory에서 register로 데이터를 가져온다.
- 연산한다.
- 결과를 register에서 Memory로 저장한다.
왜 이렇게??
연산기는 프로세서 안에 있다. register에서 접근하는게 훨씬 빠르다.
MIPS Immediate Instructions
프로그램의 연산에서 상수를 사용하는 경우는 많이 있는데 왜 그런걸까?
예시를 하나 보자.
$s3에 상수 4를 더하는 MIPS code를 보면,
lw $t0, AddrConstant4($s1)
add $s3, $s3, $t0
이와 같다. (여기서 AddrConstant4는 상수4가 있는 메모리 주소를 가리킨다)
분명 Memory에서 데이터를 가져오는 것은 느리다. lw를 사용하지 않는 방법이 있다. 그 방법은 operands 중 하나가 상수인 산술연산 instruction을 제공하는 것이다. 이 상수를 immediate operands라고 한다. immediate operands를 갖는 덧셈 명령어는 addi 이다. 위 코드를 똑같이 사용해보겠다.
addi $s3, $s3, 4
이렇게 Memoey에 접근하지 않아도 상수는 연산가능한 instructions 덕분에 연산속도가 빨라지게 된다. 여기서 설계원칙 중 또 하나의 원칙을 알 수 있다.
Design Principle 3 : Make the common case fast
자주 생기는 일을 빠르게 만들어라.
- Small constants are common
- Immediate operand avoids a load instruction
MIPS 상수 중 0은 유용하게 사용된다.
MIPS에서 0은 항상 0의 값을 가진다. 덮어씌우기가 불가능하다.
0은 registers 간 이동에 매우 유용하게 사용된다.
add $t2, $s1, $zero
$s1과 0을 더한 값을 $t2에 넣는 것인데, 0을 더하기 때문에 $s1의 값이 고스란히 $t2에 들어가게 된다.
즉, $s1을 $t2에 옮긴 것이다.
[참고]
Computer Organization and Design 5th Edition. The Hardware/Software Interface / 저자 : David A. Patterson, John L. Hennessy / 출판 : ELSEVIER
'IT > 컴퓨터구조' 카테고리의 다른 글
[ 컴퓨터구조 ] MIPS Design Principles (0) | 2020.10.22 |
---|---|
[ 컴퓨터구조 ] MIPS Instructions (+Instruction to binary) (3) | 2020.10.22 |
[ 컴퓨터구조 ] ISA (Instruction Set Architecture) (0) | 2020.09.01 |
[ 컴퓨터 구조 ] 하드웨어 연산 (Operation of Computer Hardware) (0) | 2020.05.01 |
[ 컴퓨터 구조 ] Floating Point (0) | 2020.04.28 |
댓글