하드웨어나 컴파일러가 효율적으로 빌드할 수 있는 언어를 찾는 것.
장치의 단순성
MIPS (Microprocessor without Interlocked Pipeline Stages)
add a, b, c # a = b + c
sub a, b, c # a = b - c
f = (g+h) - (i+j)
;add t0, g, h # t0 = g + h
add t1, i, j # t1 = i + j
sub f, t0, t1 # f = t0 - t1 = (g+h) - (i+j)
설계 원칙 1 : 단순함은 규칙성을 좋아한다..!
(1) 모든 산술 연산은 3개의 operands를 가진다.
(2) 규칙성은 implementation을 단순하게 만든다.
(3) 단순함은 저비용으로 더 높은 성능을 가능케 한다.
설계 원칙 2 : 작은 것이 더 빠르다.
레지스터 32개가 아니라 무지하게 많은 registers가 있으면?
(1) 프로그래머에게 편리함
(2) 그러나, 전기신호가 멀리까지 전달되어야 함
(3) 결국 clock cycle time이 증가하여 성능이 떨어짐
f = (g+h) - (i-j)
;/* int f, g, h, i, j; # 고급언어에서 이렇게 선언되었다고 가정
f, g, h, i, j # 이 변수들은 각각 $s0, $s1, $s2, $s3, $s4와 대응
*/
[Answer]
add $t0, $s1, $s2
add $t1, $s3, $s4
sub $s0, $t0, $t1
배열과 구조체
메모리(Memory)
데이터 이전 명령어(Data transfer instructions)
reg
memory
# reg ← memoryreg
memory
# reg → memory참고 :
lw
는 load word,lh
는 load half word,lb
는 load byte이고,
sw
는 store word,sh
는 store half word,sb
는 store byte이다.
C언어에서 배열 접근 방식 (2개) :
(1) direct addressing
char B[100], x, *p B;
p += 3; x =* p;
(2) base addressing
char B[100], x;
x = B[3];
e.g. g = h + A[8];
/* A의 base Address는 레지스터 $s3에 저장되었다고 가정
고급언어에서 int g, h, A[100]; 라고 선언되었다고 가정
*/
[Answer]
lw $t0, 8($s3) # Wrong Answer
// $t0는 A[8]을 얻을까? ⋯ (X)
# byte 단위로 32를 적어주어야 함!!
// 왜냐하면 int는 한 index당 4byte이기 때문!! (4byte*8=32)
add $s1, $s2, $t0
# g = h + A[8]
Byte addressing
할당 제한(a.k.a memory alignment restriction)
엔디안(Endianness)
lw $s1, 200($zero)
sw $s2, 100($zero)
Example: A[12] = h + A[8] ;
/* A의 base address를 레지스터 $s3에 저장한다고 가정
h가 $s2에 저장된다고 가정
*/
[Answer]
lw $t0,32($s3) # 임시 레지스터. 메모리 A[8]을 레지스터 $t0에 load
add $t0,$s2,$t0 # 임시 레지스터. 결과인 h+A[8]을 $t0에 저장
sw $t0,48($s3) # 다시 레지스터 $t0(결과값)을 메모리 A[12]에 store
상수 피연산자
If, 상수 피연산자없이 $s3와 4를 더한다면??
lw $t0, AddrOfConstant4 ($zero) // $t0 = constant 4
add $s3, $s3, $t0 //$s3 = $s3 + $t0 (지금 $t0는 4가 들어있음)
위 방법은 비효율적!!!
해결책 : addi
(add immediate) 명령어
addi $s3, $s3, 4
// $s3 = $s3 + 4흔하게 사용되는 것을 빠르게 만들자 !!!!