본 시리즈은 비전공자가 공부한 computer science, 그중에서도 컴퓨터구조를 정리한 글입니다. 틀린내용이 있다면 댓글로 알려주시면 정말정말 감사하겠습니다. 참고한 책은 Computer Organization and Design MIPS Edition입니다
이번에 알아볼 instruction은 slt라는 명령어로 우리가 흔히 if문에서 논리연산자를 통해서 분기처리를 할때 사용할 수 있는 알아보겠습니다.
저번에 우리가 배웠던것중에 beq와 bne가 있었는데 잠깐 복습을 해보자면 beq의 경우엔 rs와 rt가 같으면 세번째 operand가 가리키는 주소로 branch를 하고 같지 않다면 그 다음 pc로가서 instruction을 수행하라는 명령이었습니다.
근데 사실 우리가 if문을 쓸때 같다 아니다를 가지고도 분기처리를 많이 하지만 크다작다로 비교를 많이하기도하죠? 그래서 이번엔 비교를 가지고 분기처리하는 명령어에 대해서 배우는겁니다. 저도 공부하면서 이 부분에서 헷갈릴만한 요소가 없지는 않았어서 한번 차근차근 정리해보겠습니다
let a = 10
let b = 20
if a > b {
print(a)
}
뭐...이런 아주 간단한 코드가 있다고 가정하고 설명을 해보겠습니다.
MIPS에는 slt
라는 instruction이 존재합니다. 이 instruction은 총 3개의 operand를 가지고 있습니다
stl rd, rs, rt
우리가 지금까지 공부했던대로 보면 rs와 rt의 값을가지고 stl라는 연산을 수행하고 그결과를 rd라는 destination register에 임시로 저장을 해주는 플로우대로 수행이 됩니다. MIPS라는게 하나의 규칙이어서 그런지 대충 이렇게 동작하겠거니하면 다 비슷하게 동작하더라고요
이 연산을 하게되면 그러면 rd에는 어떤 값이 들어가는걸까요?? 결론부터 말씀드리면 rs가 rt보다 작으면 1이 들어가고 아니면 0이 들어가는 연산
이 slt입니다.
처음에 이 연산을 왜 이렇게 하지? 아니 그러면 저거 결과를 가지고 분기처리를 어떻게하지?라는 의문이 들었었는데 사실 답은 꽤나 간단합니다. bne
와 함께 사용하면 우리가 원하는 연산을 수행할 수 있게됩니다.
slt $s0, $s3, $s4
bne $s0, $zero, Target
자 slt와 bne를 함께 사용한 값비교를 통한 분기처리 assembly text인데요 한번 해석을 차근차근 해보죠.
예를 들어서 s3에 10이라는 값이 들어가있고 s4에 20이라는 값이 들어가 있다고 가정을 해봅시다. 그러면 10와 20을 비교했을떄 10이 작으니까 참이고 그러면 s0에는 1이라는 값이 들어가게되겠죠 그리고나서 1과 0을 두번째줄에서 비교하는데 bne이니까 같지 않다면 Target이 가리키는 pc로가서 instruction을 수행하게되겠네요. 여기서는 1과 0이므로 Target으로 가서 명령을 실행할겁니다. Target의 명령이 a라는 값을 print해라라는 명령이라면 저 위에있는 코드의 결과와 같아질겁니다.
이것이 기본적인 slt instruction의 실행입니다. 실제 spim에서도 한번 볼까요
맨 위에줄을 보면 $19에 -1을 넣고 $20에 1을 넣었습니다. 그리고 다다음 instruction이 $19와 $20을 slt 연산을 하게되겠네요 그렇다면 -1이 1보다 less than하기때문에 $16에는 1이라는 값이 저장될거고 bne연산을 통해 같지 않으면 offset 8만큼 떨어진 곳으로 branch를 하게됩니다. 하나의 instruction당 4byte기 때문에 두칸떨어진 sltu $16, $19, $20
이 실행되겠네요
어쩃든 slt도 연산의 한 종류고 우리가 보통 bit wise연산을 하는것이 아니라 계산을하는 연산에서는 값들의 부호가 있는 signed로 봐줘야한다고 배웠습니다. 그렇다면 사실 slt의 경우도 register에 들어있는 각각의 값들도 기본적으로는 signed로 봐주는게 맞지만 31bit로 표현하고싶은 값보다 더 큰 값을 가지고 slt 연산을 하고싶을때는 unsigned 연산을 하면됩니다. 간단하죠?
예시를 한번 들어보겠습니다
$s3 = 1111 1111 1111 1111 1111 1111 1111 1111
$s4 = 0000 0000 0000 0000 0000 0000 0000 0001
1. slt $s0, $s3, $s4
2. sltu $s0, $s3, $s4
첫번째 slt연산의 경우에 기본적으로 slt는 계산연산이기때문에 각각의 값들을 signed로 봅니다. 그렇다는 말은 s3에 들어있는 값은 -1로 s4에 들어있는 값은 1로 본다는 뜻이고 그렇게되면 s0에는 참이기때문에 1이 들어가게 됩니다.
하지만 두번째 연산의 경우엔 모든 요소를 unsigned로 봐야하기때문에 42억땡땡땡과 1을 비교해서 less than하지 않기때문에 0이라는 값이 s0에 저장되게 됩니다.
근데 우리가 사실 코드를 쓸때 if a>b {print(a)}
이렇게 쓰는게 훨씬 편하기때문에 assembly text에서도 이런점을 고려한건지는 모르겠으나 pseudo instruction이 존재합니다.
blt $s3, $s4, Target
이렇게 instruction text를 작성해주면 s3의 값과 s4의 값을 less than한지를 비교해서 만약에 참이라면 Target으로 branch를 해주게 되고 실제로 이 pseudo instruction은
slt $1, $s3, $s4
bne $1, $0, Target
이렇게 변환이 되어서 수행하게됩니다.
지금까지 배웠던 모든 instruction을 이용해서 Loop Statement를 complile하는 방식에대해서 알아보겠습니다.
간단하게 이야기해서 while문같은 loop code를 어떻게 complie하는지를 배우는거라고 생각하면 됩니다 그런의미에서 간단한 코드를 하나 가져와보겠습니다
var i = 1
while arr[i] == k {
i += 1
}
// i in $s3, k in $s5, address of arr in $s6
이 코드를 컴파일 해보면 어떤 assembly text가 만들어지는지 결과를 보고 한번 한줄한줄 해석해보겠습니다
Loop: sll $t1, $s3, 2
add $t1, $t1, $s6
lw $t0, 0($t1)
bne $t0, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit: ...
꽤나 복잡해보이긴하지만....한줄한줄보면 괜찮을거예요^^
우선sll
을 보면 s3에 있는 값을 shift left
하라고 하네요 두칸을? 배웠던 기억을 더듬어보면 sll의 역할은 두칸을 옮기는것이라고 배웠지만 수식적인 해석은 조금 달랐습니다. 바로 2의 n제곱을 곱하는거였습니다. 그러니까 s3에 있는 i라는 값에다가 2의 2제곱인 4를 곱해주라는 instruction입니다.
갑자기 너무 뜬금없이 4를 곱하라고 하니까 좀 당황스러울수있지만 왜 이런 명령어가 필요햇는지 한번 생각을 해봅시다. 우리는 arr의 index를 하나씩 늘려가면서 요소를 찾아서 그 값이랑 k라는 값이랑 비교를 해야합니다. 그죠?
근데 우리가 arr를 생각해보면 각각의 주소에 데이터를 저장하고 있을텐데 이녀석 Int를 담고있는 arr니까 각각의 요소가 4byte겠죠? 그러면 당연히 우리가 i는 1씩늘어나더라도 주소는 4개씩 늘어나는 셈이기때문에 우리가 값을 index를가지고 받아오기위해서는 4byte씩 주소를 늘려야합니다. 그걸위한 연산 instruction이라고 생각하시면 됩니다.
add $t1, $t1, $s6
를 보면 s6에는 지금 array의 시작주소가 있습니다. 거가에다가 index * 4
라는 값을 더해준다는 뜻은 index의 데이터를 찾을 주소를 t1에다 저장하라는 뜻이됩니다.
lw $t0, 0($t1)
그리고 나서 t1주소의 값을 t0에 load하라는 명령어를 거쳐서 실제로 원하는 index의 값을 t0에 저장하게되고
bne $t0, $s5, Exit
그 값과 k값을 비교해서 같지 않으면 Exit으로 branch를 하라고 합니다. 근데 우선 우리는 같다고 가정해보겠습니다.
addi $s3, $s3, 1
이를 통해 index를 1증가시켜주고 j Loop
를 통해 다시 Loop의 시작점으로 돌아가게됩니다.
3주차 컴퓨터구조의 메인 주제는 slt와 loop를 어떻게 complie하는지에 대해 알아봤습니다. 다음 포스팅에서는 함수와스택
에대해서 포스팅해보겠습니다
전공책을 기반으로 정리하는 글이기때문에 나름대로 최대한 이유가있는 설명을 한다고는하지만 분명히 틀리거나 추가로 들어가야할 내용이 있을수있기때문에 언제든지 댓글로 알려주세요!
그럼 20000!!!!