※ Fibonacci Sequence using Mips
- Condition
A >=90
90 > B >= 70
70 > C >= 50
50 > D >= 30
30 > F >= 10
- Tool
- SPIM : Simulator of MIPS Processor
(Software in order to execute assembly code
- Instruction Set
- Result Screen
- Source Explanation
main:
li $v0, 4
la $a0, string
syscall
li $v0, 5
syscall
콘솔창에 "seed
input = "을 출력하기 위해 $v0에 4를 저장하여 string을 콘솔에 출력하는 시스템 콜을 통해 $a0레지스터에 string레이블의 주소값을 저장한다. 후에 system콜을 하게 되면 "seed
input = "이 출력된다. 데이터 스택공간에 string:
.asciiz "seed input = "이 정의 해놨다.
li $t0, 0
li $t1, 5
la $t2, array
5개의 값을 랜덤으로 받기 위해 $t0에 시작위치0과 $t1에 끝 위치 5 (0<=
<5)를 이용할 것이다. $t2에는 array레이블 주소를 저장한다. $t2를 이용해 랜덤한 5개의 수를 저장할 것이다.
Loop1:
beq $t0, $t1, L1
add $a0, $zero, $v0
$t0과 $t1이 같은지 비교하여($t1은 고정하고 $t1을 1씩 증가시킬 것이다.) 같게 되면 랜덤한 수가 모두 입력이 완료 되었으므로 L1레이블로 이동한다.
addi $sp, $sp, -4
sw $ra, 0($sp)
jal RandomNumberGenerator
lw $ra, 0($sp)
addi $sp, $sp, 4
함수 호출전에 스택공간을 할당후 현재 $ra에 저장된 값을 보존하기 위해 스택 공간에 저장한다.
RandomNumberGenerator 함수를 호출하기위해 jal 명령어(이 다음 명령어의 주소를 $ra에 저장한다)를 통해 RandomNumberGenerator레이블 위치로 이동한다.
sw $v0, 0($t2)
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop1
RandomNumberGenerator 함수를 빠져나온 후 반환된 값을 $t2 배열에 하나씩 저장할 것이다. 저장후 다음 값을 저장해야하므로 $t0은 5번 반복을 위해 1을 증가 시키고 $t2의 array주소는 4를 더하여 다음 인덱스를 가르킨다.
L1:
랜덤한 수가 모두 입력이 완료 되었으면 L1레이블 이후로 진행 된다.
li $t0, 0
li $t1, 5
la $t2, array
Loop2:
beq $t0, $t1, L2
$t0(5번 반복하기 위해 사용할 레지스터)와 $t1(5번)을 이용하여 beq명령문을 통해 조건이 두 숫자가 같으면 즉 5=5가 된다면 L2레이블로 이동한다.
lw $t3, 0($t2)
li $v0, 1
add $a0, $zero, $t3
syscall
배열의 값을 뽑는 것은 ‘3번 문제’나 그 전에도 많이 설명했으므로 생략하겠습니다. 현재 $t2 array주소가 가르키는 숫자를 시스템 콜을 이용하여 출력한다.
slti $t4, $t3, 30
beq $t4, $zero, Else1
li $t5, 'F’
li $v0, 11
add $a0, $zero, $t5
syscall
slti는 slt와 비슷하다 2번째 비교값이 상수값(imediate)인 것이 차이점이다. $t3(array주소가 가르키는 값이 저장된 레지스터)와 숫자 30을 비교하여 $t3<30이면 $t4에 1이 저장된다.
beq명령어를 통해 $t4와 0이 같으면 즉 30보다 크다면 Esle1레이블로 이동한다.
30미만이라면 character문자를 콘솔창에 출력하는 시스템콜($v0=11)하여 $t5에 저장된 ‘F’문자를 $a0에 저장하여 출력한다.
li $v0, 11
li $a0, '\n'
syscall
5개의 숫자를 구분하기 위해 ‘\n’ 줄바꿈을 출력한다.
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop2
$t0에 1을 더하고 (5번 반복하기 위해) array주소는 다음 값을 불러오기 위해 4를 더한다. (배열 integer값을 4바이트로 구분하기 때문이다.)
다시 반복하기 위해 Loop2레이블로 점프한다.
Else1:
30이상인 숫자가 오게 되면 Else1 레이블로 오게된다.
위와 같은 방법이므로 중요한 요점만 말하겠습니다.
slti $t4, $t3, 50
beq $t4, $zero, Else2
li $t5, 'D’
li $v0, 11
add $a0, $zero, $t5
syscall
li $v0, 11
li $a0, '\n'
syscall
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop2
50보다 작은 숫자( 30<=
<50)이라면 ‘D’가 출력된다. 출력 후 Loop2로 점프한다. 그렇지 않으면 Else2레이블로 이동한다.
Else2:
slti $t4, $t3, 70
beq $t4, $zero, Else3
li $t5, 'C'
li $v0, 11
add $a0, $zero, $t5
syscall
li $v0, 11
li $a0, '\n'
syscall
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop2
70보다 작은 숫자( 50<= <70)이라면 ‘C’가 출력된다. 출력 후 Loop2로 점프한다. 그렇지 않으면 Else3레이블로 이동한다.
Else3:
slti $t4, $t3, 90
beq $t4, $zero, Else4
li $t5, 'B'
li $v0, 11
add $a0, $zero, $t5
syscall
li $v0, 11
li $a0, '\n'
syscall
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop2
90보다 작은 숫자( 70<=
<90)이라면 ‘B’가 출력된다. 출력 후 Loop2로 점프한다. 그렇지 않으면 Else4레이블로 이동한다.
Else4:
li $t5, 'A'
li $v0, 11
add $a0, $zero, $t5
syscall
li $v0, 11
li $a0, '\n'
syscall
addi $t0, $t0, 1
addi $t2, $t2, 4
j Loop2
90이상( >=90)이라면 ‘A’가 출력된다. 출력 후 Loop2로 점프한다.
L2:
jr $31
5번의 반복이 끝나면 L2레이블로 온다. (Loop2: beq
$t0, $t1, L2)
main함수를 호출했던 곳의 바로 다음 명령어로 돌아간 후 프로그램은 종료된다.
-----------------------------------------------------------------------------
RandomNumberGenerator:
li $t3, 65533
mult $a0, $t3
mflo $a0
srl $a0, $a0, 5
addi $a0, $a0, 1
li $t3, 654
div $a0, $t3
mflo $a0
li $t3, 91
div $a0, $t3
mfhi $a0
랜덤한 수를 만들기 위해 (처음으로 부른 함수라면 입력된 seed값) 바로 전에 만들어진 랜덤한 수를 이용해 랜덤한 수를 만들 것이다. 불러온 값 $a0에 $t3(65533) 큰 숫자를 더하고 두 수를 곱하는 mult명령어를 사용한다. 주소는 32비트(8바이트)이므로 두 수를 곱하게 되면 범위를 넘어서는 값이 나온다. mfhi, mflo 를 이용하여 상위 8바이트나 하위 8바이트로 자른다. mflo는 하위 8바이트이므로 두 수를 곱한 값의 하위 8바이트를 $a0에 저장한다.
srl명령어를 사용하여 오른쪽으로 5비트 이동한다. 1을 다시 더하고 654를 div명령어를 사용하여 나누어 몫을 $a0에 저장한다. div명령어는 mflo가 몫을 나타내며 mfhi는 나머지를 나타낸다.
랜덤한 수를 위해 아무 숫자나 가감승제 하였다. 이제 10~100사이의 숫자를 구하기 위해 $a0을 91로 나누어 나머지값(div후 mfhi이용)을 $a0에 저장한다. 이러면 0~90까지인 범위가 된다.
add $v0, $a0, 10
jr $ra
0~90까지 범위의 숫자에 10을 더하게 되면 10~100인 숫자가 나오게 된다. 그 숫자를 반환값에 사용할 레지스터 $v0에 저장후 RandomNumberGenerator함수를 호출한 곳으로 돌아간다.
-----------------------------------------------------------------------------
.data
string: .asciiz "seed input =
"
array: .word 0:5
데이터 스택공간에 "seed
input = "을 string레이블에 저장하고 array는 word0:5
즉 6개의 4바이트 공간을 선언한다.
-----------------------------------------------------------------------------
댓글 없음:
댓글 쓰기