본문 바로가기
컴퓨터.반도체

컴퓨터 구조1 - MIPS 예제 풀이 (Load store shift)

by JROK 2023. 5. 29.

Load / Store

문제를 풀기 전에 새로운 명령어인 lw와 sw에 대한 설명이 필요하겠죠?

 

MIPS 어셈블리어에서 lw는 "load word"를 나타내며, 메모리에서 4바이트(한 워드)를 로드하여 레지스터에 저장합니다. 예를 들어, "lw $t0, 0($s0)"는 $s0 레지스터가 가리키는 주소에서 워드를 로드하여 $t0 레지스터에 저장합니다.

반대로, sw는 "store word"를 나타내며, 레지스터의 값을 메모리에 저장합니다. 예를 들어, "sw $t0, 0($s0)"는 $t0 레지스터의 값을 $s0 레지스터가 가리키는 주소에 저장합니다.

즉, lw와 sw 명령어는 레지스터와 메모리 간의 데이터 이동을 담당합니다.

 

이제 문제를 풀어볼까요?


# E4
li $1, 268435456   # $1 <- (1<<28)
li $2, 11          # $2 <- 11
sw $2, 0($1)       # $2->0($1)

# E5
li $1, 268435456   # $1 <- (1<<28)
lw $2, 0($1)       # $2 <-0($1)
lw $3, 4($1)       # $3 <-4($1)
sub $4, $2, $3     # $4 <-$2-$3
sw $4, 8($1)       # $4 ->8($1)
```

해당 코드는 먼저 E4 라벨에서 상수 11을 메모리 주소 0x10000000에 저장합니다. 그 후, E5 라벨에서 메모리 주소 0x10000000과 0x10000004에 저장된 값을 불러와 뺀 값을 메모리 주소 0x10000008에 저장합니다. 메모리 주소를 사용하지 않고 상수로 대체하였습니다.


Shift 예제 1

Shift는 당연히 옮기다 라는 뜻입니다. 2진수로 생각했을때 0x0010이라는 주소값을 가진 $1을 srl 1하여 $4에 저장한다면

$4에는 0x0001에저장되겠죠?


다시 풀이 전에 명령어의 의미에 대해 파악해봅시다

이 코드에서 li 명령어는 "load immediate"의 약어로, 즉 상수 값을 레지스터에 로드하는데 사용됩니다.

sll 명령어는 "shift left logical"의 약어로, 비트를 왼쪽으로 시프트하고 오른쪽에 0을 추가합니다. 즉 2진수로 생각하였을 때 한칸 왼쪽으로 보내는 것이니까 해당 값의 2제곱을 해준다고 생각하면 편합니다.

마지막으로, srl 명령어는 "shift right logical"의 약어로, 비트를 오른쪽으로 시프트하고 왼쪽에 0을 추가합니다. 이 것도 위와 마찬가지로 1/2를 해준다고 생각하면 되겠죠

 

 

그럼 풀어봅시다

 

 

li $1, -1  # $1 = -1
sll $2, $1, 1  # $2 = $1 << 1
sll $3, $1, 2  # $3 = $1 << 2
srl $4, $1, 1  # $4 = $1 >> 1
              # srl shift right logically
srl $5, $1, 2  # $5 = $1 >> 2

Shift 예제 2

먼저 사용된 명령어에 대해 알아봅시다.

 

이 코드에서 li 명령어는 "load immediate"의 약어로, 즉 상수 값을 레지스터에 로드하는데 사용됩니다.

mul 명령어는 "multiply"의 약어로, 곱셈을 수행합니다. div 명령어는 "divide"의 약어로, 나눗셈을 수행합니다.

 

sll 명령어는 "shift left logical"의 약어로, 비트를 왼쪽으로 시프트하고 오른쪽에 0을 추가합니다. 마지막으로, srl 명령어는 "shift right logical"의 약어로, 비트를 오른쪽으로 시프트하고 왼쪽에 0을 추가합니다.

 

이 때 새로운 내용이 추가됩니다. sra 명령어는 "shift right arithmetically"의 약어로, 비트를 오른쪽으로 시프트하고 왼쪽에 부호 비트를 추가합니다. 예를 들어, -1010 (-10)을 1비트 오른쪽으로 시프트하면 -0101 (-5)가 됩니다. 따라서, srl 명령어는 무조건적으로 0을 채우고, sra 명령어는 부호를 유지합니다. 이것이 srl과 sra의 주요 차이점입니다.

 

왜 도대체 sra를 사용할까요? 어짜피 오른쪽으로 한칸 옮길거면 srl을 사용하면 되지 않을까요?

sra 명령어는 부호 비트를 유지하기 때문에, 논리적으로 부호 있는 수에 대한 오른쪽 쉬프트 작업에 효과적입니다. 예를 들어, 음수 값이 있는 경우 srl 명령어를 사용하면 부호 비트가 0으로 채워져서 결과 값이 잘못된 경우가 발생할 수 있습니다. 반면에, sra 명령어는 부호 비트를 유지하기 때문에, 결과 값이 항상 올바르게 계산됩니다.

또한, sra 명령어는 부호 있는 수의 나눗셈을 계산하는 데에도 사용됩니다. 이것은 부호 있는 수의 나눗셈을 계산하기 위해서는 먼저 sra 명령어를 사용하여 수를 쉬프트한 다음, div 명령어를 사용하여 나누는 것이 일반적이기 때문입니다.


그럼 문제를 풀어봅시다

 

 

 

 

li $1, 15  # $1 = 15
li $2, -15  # $2 = -15
mul $3, $1, 2  # $3 = $1 * 2
sll $4, $1, 1  # $4 = $1 << 1
mul $5, $2, 4  # $5 = $2 * 4
sll $6, $2, 2  # $6 = $2 << 2
div $7, $1, 4  # $7 = $1 / 4
srl $8, $1, 2  # $8 = $1 >> 2
div $9, $2, 4  # $9 = $2 / 4
srl $10, $2, 1  # $10 = $2 >> 1
sra $11, $2, 1  # $11 = $2 >> 1  (sra shift right arithmetically)

 

좀 길어보이지만 하나씩 대입하며 풀면 수월하게 풀릴 겁니다

 

C code to MIPS assembly (Logic)

 

 

해당 문제는 C언어를 MIPS로 푸는 것입니다. 사실 위에 내용들도 비슷한 의미였는데요, C언어는 인간의 언어에 가까운 높은 단계의 언어이고, MIPS는 기계에 가까운 낮은 단계의 언어입니다 ( low level, high level )

 

높고 낮다고 해서 좋은 것은 아니고 기계와 가까우면 낮고, 인간과 가까우면 높은 하나의 층을 생각하면 좋을 것 같습니다

2번째 단계에 c가 있고 4번째에 assembly가 있는 것을 볼 수 있죠?

 

c언어를 안다는 전제하에 해당 문제를 해결해봅시다

 

먼저 사용되는 명령어에 대해 설명해보겠습니다

and, or, xor, nor 명령어는 각각 논리곱, 논리합, 배타적 논리합, 논리 부정 OR을 수행합니다.

addi 명령어는 "add immediate"를 의미하며, 레지스터에 상수 값을 더합니다.

 

 

 lw $t0, a  # $t0 = a
    lw $t1, b  # $t1 = b

    and $t2, $t0, $t1  # $t2 = $t0 & $t1
    or $t3, $t0, $t1  # $t3 = $t0 | $t1
    xor $t4, $t0, $t1  # $t4 = $t0 ^ $t1
    nor $t5, $t0, $0  # $t5 = ~(t0 | 0)
    addi $t5, $t5, -1  # $t5 = ~t0

    sw $t2, c  # c = $t2
    sw $t3, d  # d = $t3
    sw $t4, e  # e = $t4
    sw $t5, f  # f = $t5


결론

오랜만에 컴구 공부했더니 머리 아프네요. 앞으로 이런 문제들의 해결에 대한 시간이 계속 될 것 같습니다. 네 c에서 MIPS로 바꾸는 과정이죠 파이팅!

댓글