명령어 (15) - MIPS 프로그래밍 해보기

컴퓨터구조

2020. 5. 4. 15:08

1. MARS Simulator

 

MARS MIPS simulator - Missouri State University

V4.5,  Aug. 2014 (jar archive including Java source code) Note: Is your MARS text unreadably small? Download and use a new release Java 9, which contains a fix to automatically scale and

courses.missouristate.edu

이 곳에서 MIPS 코드를 직접 작성, 어셈블해볼 수 있는 MARS 시뮬레이터를 다운로드 받을 수 있다.

 

2. MARS 사용법

  • F3 : 실행
  • F5 : 한번에 어셈블
  • F7 : 스텝별로 어셈블 (앞으로)
  • F8 : 스텝별로 어센블 (뒤로)

 

3. 연습한 MIPS 코드

1) Loop

# Code Section
.text
.globl main

main:
	li $a1 1
	jal loop
	
	move $a0 $v0
	mul $a0 $a0 2
	
	li $v0 1  # print
	syscall
	
	li $v0 10  # exit
	syscall
	
loop:
	add $a1 $a1 1
	bne $a1 10 loop
	beq $a1 10 return

return:
	move $v0 $a1
	jr $ra
	

 

2) Function

# Data Section
.data
result_msg: .asciiz "result : "  
line_msg: .asciiz "\n"  

# Code Section
.text
.globl main

# int addMul(int a, int b, int c, int d){
# 	int x = addition(a, b);
# 	int y = addition(c, d);
# 	int z = multiply(x, y);
#	return z;
# }
#
# int addition(int a, int b){
#	int c = a + b;
#	printf("result : %d\n", c);
# 	return c;
# }	
# 
# int multiply(int a, int b){
#   	int c = a * b;
#	printf("result : %d\n", c);
# 	return c;
# }
#
# int main(){
#	addMul(2, 3, 4, 5);
#	return 0;
# }

main:
	li $a0 2
	li $a1 3
	li $a2 4
	li $a3 5
	jal addMul
	
	li $v0 10  # exit
	syscall

addMul:
	addi $sp $sp -20	# make stack frame = int[5] (4byte * 5 = 20)
	sw $ra 16($sp)		# store ra
	sw $a0 12($sp)		# store a0
	sw $a1 8($sp)		# store a1
	sw $a2 4($sp)		# store a2
	sw $a3 0($sp)		# store a3
	
	lw $a0 12($sp)		# load a0 (12 + 0)
	lw $a1 8($sp)		# load a1 (8 + 0)
	jal addition
	addi $sp $sp -4		# allocation (x)
	sw $v0 0($sp)		# assignment (x)
	
	lw $a0 8($sp)		# load a2 (4 + 4)
	lw $a1 4($sp)		# load a3 (0 + 4)
	jal addition
	addi $sp $sp -4		# allocation (y)
	sw $v0 0($sp)		# assignment (y)
	
	lw $a0 4($sp)		# load x
	lw $a1 0($sp)		# load y
	jal multiply
	addi $sp $sp -4		# allocation (z)
	sw $v0 0($sp)		# assignment (z)
	
	lw $ra 28($sp)	  	# load return address (16 + 12)
	addi $sp $sp 32  	# delete stack frame (20 + 12)
	jr $ra			# jump to ra
	
multiply:
	addi $sp $sp -12	# make stack frame = int[3]
	sw $ra 8($sp)		# store ra
	sw $a0 4($sp)		# store a0
	sw $a1 0($sp)		# store a1
	
	la $a0 result_msg
	li $v0 4		# printf("result : ")
	syscall
	
	lw $s0 4($sp)		# a = frame[1]
	lw $s1 0($sp)		# b = frame[2] 
	mul $t0 $s0 $s1		# x = a + b;
	
	li $v0 1
	move $a0 $t0		
	syscall			# printf(x)
	
	la $a0 line_msg
	li $v0 4		# printf("\n")
	syscall
	
	move $v0 $t0		# return x;
	lw $ra 8($sp)		# load return address
	addi $sp $sp 12		# delete stack frame
	jr $ra			# jump to ra
		
		
addition:
	addi $sp $sp -12	# make stack frame = int[3]
	sw $ra 8($sp)		# store ra
	sw $a0 4($sp)		# store a0
	sw $a1 0($sp)		# store a1
	
	la $a0 result_msg
	li $v0 4		# printf("result : ")
	syscall
	
	lw $s0 4($sp)		# a = frame[1]
	lw $s1 0($sp)		# b = frame[2] 
	add $t0 $s0 $s1		# x = a + b;
	
	li $v0 1
	move $a0 $t0		
	syscall			# printf(x)
	
	la $a0 line_msg
	li $v0 4		# printf("\n")
	syscall
	
	move $v0 $t0		# return x;
	lw $ra 8($sp)		# load return address
	addi $sp $sp 12		# delete stack frame
	jr $ra			# jump to ra
		

 

4. 새롭게 알게된 명령어

  • li (load immediate) : 레지스터에 immediate value를 로드한다. (원래 mips에 없는데 어셈블러가 처리해줌)
  • la (load address) : 레지스터에 주소를 로드한다
  • move : 한 레지스터 안에 있는 값을 다른 레지스터로 옮긴다 (원래 mips에 없는데 어셈블러가 처리해줌)
  • syscall : OS의 함수를 호출한다. 이때, 함수 종류는 v0, 파라미터는 a0~3으로 설정한다
  • .data : 전역변수 영역의 시작을 알린다
  • .text : 테스트(코드)영역의 시작을 알린다
  • .globl : 시작함수를 지정한다
  • # : 주석처리에 사용한다