Home
Skip to content

MIPS Assembly – Find Prime Numbers

In this project, the MIPS assembly language is used to find Prime Numbers. Annually, close to a hundred million MIPS-based processors are used in a wide range of products. Learning assembly language programming exposes one to not only the details of the instruction set, but also makes one aware of how compilers produce assembly/machine language code from a high-level language program. Assembly language programming is still used to write programs in which speed or size are critical or to exploit hardware features that have no analogues in high-level languages.




Follow jayweezee on Twitter




Here’s the code to find Prime Numbers in MIPS Assembly:

#***************************************
# Jason Weber, Nick Stumpos
#
#***************************************
 
	.data
	.align 4
DONE: .asciiz "\nDone.\n "
MSG4: .asciiz " "
new_line: .asciiz "\n";
#----------------------------------------------------------------
# Procedure: main
#       1. Iterate over the integers up to the 100th prime
#       2. Uses test_prime to to test if each integer is prime
#       3. Prints the first 100 numbers that are prime
#----------------------------------------------------------------
       .text
       .globl main
main:
	add 	$fp, $zero, $sp;		# set the frame pointer
	addi 	$s0, $zero, 0;			# put 0 in  s0 (number of primes found)
	addi 	$s1, $zero, 100;		# put 100 in  s1 (number were looking for)
	addi 	$s2, $zero, 0			# put 0 in s2	(number were checking)
	addi 	$s3, $zero, 10;			# put 10 in s3 for various checks	
	addi 	$s4, $zero, 100;		# put 100 in s4 for various checks	
main_loop:
 
	beq  	$s0, $s1, main_loop_done;	
	add 	$a0, $zero, $s2;		# put number to test as first arg 
	jal 	test_prime;			# call test_prime function
	beq 	$v0, $zero, prime_continue;	# was it false
	addi 	$s0, $s0, 1;			# inc s0 (count of primes)
	sub 	$t0, $s2, $s3;
	bgez 	$t0, not_single;		# is $s2 a single digit 
	li 	$v0, 4;       			# print a space before the number
	la 	$a0, MSG4;
	syscall;
not_single:  
	sub 	$t0, $s2, $s4;			
	bgez 	$t0, not_double;		# is it a double or single digit
	li 	$v0, 4;       			# print a space before the number
	la 	$a0, MSG4;
	syscall;
not_double:  
        li	$2,1;				# system call code for print int
        add 	$4, $zero, $s2;			# the prime number to be printed
	syscall;
	li 	$v0, 4;       			# print a space after the number
	la 	$a0, MSG4;    			
	syscall;
	div 	$s0,$s3;			# is this a place for a newline
	mfhi 	$t0;
	bgtz 	$t0, prime_continue; 		# a mult of 10?
	li 	$v0, 4;       			# if so print a new line
	la 	$a0, new_line;    			
	syscall;
 
prime_continue:
	addi 	$s2, $s2, 1;			# inc s4(number to be tested)
	beq 	$zero,$zero, main_loop;		# loop
 
main_loop_done:
	li 	$v0, 4;       			# print done
	la 	$a0, DONE;    			
	syscall;
	li	$v0, 10      			# system call to exit
	syscall;
 
#-----------------------------------------------------
# Procedure: test_prime
# Input: integer value n
# Return: 1 if n is prime and 0 if n is not prime
#
# of the callee saved registers the subroutine test_prime uses
# s2, s3 so we will save those to the stack
# as well as the old fp, and return pointers in 
# the beginng and restore them in the end.
# we will then set the new $fp to keep with convention
# although we dont ever use it
#---------------------------------------------------------
       .text
test_prime:
	addi	$sp,$sp,-4;			# dec sp
	sw	$ra,($sp);			# save return address on stack
	addi	$sp,$sp,-4;			# dec sp
	sw	$fp,($sp);			# save fp on stack
	addi	$sp,$sp,-4;			# dec sp
	sw	$s2,($sp);			# save s2 on stack
	addi	$sp,$sp,-4;			# dec sp
	sw	$s3,($sp);			# save s3 on stack
	addi	$sp,$sp,-4;			# dec sp
	addi	$fp, $sp, 32			# set $fp
	addi 	$s2, $zero, 1			# put 1 in s2
	bne  	$s2, $a0, not_one; 		# is the arg 1
	add 	$v0, $zero, $zero		# if so not a prime
	beq	$zero, $zero, exit_prime	# exit subroutine
not_one: 
	addi 	$s2, $zero, 2;			# put immediate value 2 in  s2
	beq 	$a0,$s2, three_done; 		# two is a prime
	div 	$a0, $s2;			# do divide
	mfhi 	$t0; 				# get remainder
	bgtz 	$t0, three;			# is it a mult of 2
	add 	$v0, $zero, $zero		# if so not a prime
	beq	$zero,$zero,exit_prime         	# exit subroutine
three:
	addi 	$s2, $s2, 1;			# put 3 in  s2
 
three_loop:
	add 	$t0, $zero, $zero		# clear reg
	mult  	$s2, $s2;			# get $s2^2
	mflo 	$s3;				# get answer. for our purposes it will always be in the lo
	sub 	$t0, $a0, $s3;			# is s2 greater than the squareroot of a0 
	bltz  	$t0, three_done; 		# if so were done
	div 	$a0, $s2;			# do divide
	mfhi 	$t0;				# get remainder
	bgtz 	$t0, three_cont; 		# is $a0 a mult of $s2  
	add 	$v0, $zero, $zero		# if so not a prime
	beq	$zero,$zero,exit_prime         	# exit subroutine
three_cont:
	addi 	$s2, $s2, 2; 			# continue skipping mults of three and evens
	beq 	$zero, $zero, three_loop; 	# go again
three_done:					# through loop so number is a prime
	addi 	$v0, $zero, 1;			# is prime so true
exit_prime:
	addi	$sp,$sp,4;			# inc sp
	lw	$s3,($sp);			# get old s3 off stack
	addi	$sp,$sp,4;			# inc sp
	lw	$s2,($sp);			# get old s2 off stack
	addi	$sp,$sp,4;			# inc sp
	lw	$fp,($sp);			# get old fp off stack
	addi	$sp,$sp,4;			# inc sp
	lw	$ra,($sp);			# get return address off stack
	addi	$sp,$sp,4;			# inc sp back to where we expect it to start
	jr 	$ra;				# go back to caller+4




Follow jayweezee on Twitter




Post a Comment

You must be logged in to post a comment.