시작하기 전
이 글은 필자가 수업시간에 들은 내용과 강의록을 토대로 정리한 글입니다.
수업 필기이다 보니, 오류가 있거나 설명이 부족한 부분이 있을 수 있습니다.
궁금하신 점이나 지적하실 점이 있다면 댓글로 달아주세요! 확인 후 내용을 추가하거나 답변해드리도록 하겠습니다 :)
레지스터 피연산자(Register Operands)
f = (g + h) - (i + j);
와 같은 코드가 있다고 가정하자. 이를 컴파일 하면,
add $t0, $s1, $s2
add $t1, $s3, $s4
sub $s0, $t0, $t1
과 같은 코드가 된다.
메모리 피연산자(Memory Operands)
-
메인 메모리는 복합적인 데이터들을 저장하기 위해 사용된다.
- 배열, 구조체, 동적 데이터(동적 할당) 등
- 또한, 모든 변수들이 레지스터 내에 저장될 수는 없기 때문에, 레지스터에 담아두지 못하는 데이터들도 메모리에 저장한다. (레지스터는 32개 밖에 없다)
-
산술 연산을 시행하려면, 데이터 전송 명령(Data transfer instruction)이 필요하다.
- 메모리로부터 레지스터로 값을 불러오거나(Load)
- 레지스터로부터 메모리로 결과를 저장한다.(Store)
-
메모리에 접근하기 위해선, 메모리 주소(Memory Address)가 필요하다.
- 메모리는 바이트 단위로 주소화 되어있다. 모든 주소는 8bit 바이트로 식별한다.
- “word” 들은 메모리 상에서 정렬(Aligned)되어 있다. 즉, 주소는 무조건 4의 배수이다.
-
MIPS는 ‘Big Endian’을 사용한다.
- 어떤 하나의 word에서 MSB(Most Significant Bit)가 가장 작은 주소에 위치한다.
- 이와 비교하여 ‘Little Endian’은 LSB(Least Significant Bit)가 가장 작은 주소에 위치한다.
- 예를 들어, 0A334B0D 라는 4 Byte 값이 있다고 가정할 때, Big Endian은
와 같이 저장하고, Little Endian은
와 같이 저장한다.
- Big Endian은 사람이 읽는 순서와 똑같이 메모리에 저장이 되기 때문에, 큰수를 표현하거나 디버깅 하는 데에 편리한 반면, Little Endian은 덧셈을 할 때 바이트를 앞에서부터 읽어나가면 되기 때문에 가산기 설계에 더 편리하다.
- 참고로, 네트워크에서 바이트 순서(Byte order)는 Big Endian이기 때문에, 그것을 전송 받는 컴퓨터가 Little Endian을 사용한다면, 별도의 변환 과정을 거쳐야 한다.
메모리 명령 예시(Memory Instructions Examples)
- load word(lw) 그리고 store word(sw)
lw $t0, 32($s3)
- 3개의 피연산자를 사용한다.
- 목적지 레지스터(Destination register)
- 오프셋(Offset) : 기본 주소(Base address)로부터 몇 칸이나 더 가야하는지 표현
- 기본 주소(Base address) : 오프셋을 적용시킬 기본 주소
레지스터 vs 메모리(Registers vs Memory)
- 레지스터가 메모리보다 더 접근하기 빠르고, 사용하기 간단하다. 예를 들어, 덧셈 연산을 수행해야 한다고 가정할 때, 레지스터는
add
하나로 해결이 가능하지만, 메모리는 lw
, add
, sw
의 3가지 과정을 거쳐야만 한다.
- 메모리 데이터로 연산하는 것은 불러오기(Load)와 저장(Store)을 필요로 한다.
- 산술 연산은 레지스터에서만 작동하기 때문이다.
- 또한, 레지스터의 수에는 한계가 있는데, 우리는 많은 수의 명령(Instruction)을 수행해야 하기 때문에, 필연적으로 메모리 데이터로 연산을 하게 된다.
- 컴파일러는 최대한 많은 수의 변수들을 레지스터로 연산하도록 해야한다.
- 오직 적게 사용되는 변수들만 메모리로 연산하게 해야한다.
- 레지스터 최적화는 효율성을 위해 매우 중요하다.
- 상수 데이터를 연산할 때는
addi
를 사용하면 된다.
addi $s3, $s3, 4
- 따로 뺄셈을 위한 명령은 없다. 그저, 음수인 상수를 사용하면 된다.’
addi $s3, $s3, -2
- MIPS에서 레지스터 0 (
$zero
)는 상수 0이다.
- 수정될 수 없는 레지스터이다.
- 보통 아래와 같이 많은 연산에 유용하다.
add $t2, $s1, $zero
- 디자인 원칙(Design Principle) 3 : 평범한 경우(Common case)를 빠르게 만들어라.
- 작은 상수는 평범하다.
- 즉각 피연산자는 불러오기(Load) 명령(Instruction)이 필요 없다. → 빠르다.
부호 없는 이진 정수(Unsigned Binary Integers)
x=xn−12n−1+xn−22n−2+⋯+x121+x020
이다.
- 범위 : 0 부터 2n−1 까지
- 8 비트를 사용한다면 → 0 ~ 255
- 16 비트를 사용한다면 → 0 ~ 65535
- 32 비트를 사용한다면 → 0 ~ 4,294,967,295