Skip to content

Instantly share code, notes, and snippets.

@dcalacci
Created September 19, 2012 03:35
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save dcalacci/3747521 to your computer and use it in GitHub Desktop.
Save dcalacci/3747521 to your computer and use it in GitHub Desktop.
simple factorial program in MIPS assembly
.globl main
.data
msgprompt: .word msgprompt_data
msgres1: .word msgres1_data
msgres2: .word msgres2_data
msgprompt_data: .asciiz "Positive integer: "
msgres1_data: .asciiz "The value of factorial("
msgres2_data: .asciiz ") is "
# every function call has a stack segment of 12 bytes, or 3 words.
# the space is reserved as follows:
# 0($sp) is reserved for the initial value given to this call
# 4($sp) is the space reserved for a return value
# 8($sp) is the space reserved for the return address.
# calls may manipulate their parent's data, but parents may not
# manipulate their child's data.
# i.e: if we have a call A who has a child call B:
# B may run:
# sw $t0, 16($sp)
# which would store data from $t0 into the parent's return value register
# A, however, should not(and, in all cases I can think of, cannot) manipulate
# any data that belongs to a child call.
.text
main:
# printing the prompt
#printf("Positive integer: ");
la $t0, msgprompt # load address of msgprompt into $t0
lw $a0, 0($t0) # load data from address in $t0 into $a0
li $v0, 4 # call code for print_string
syscall # run the print_string syscall
# reading the input int
# scanf("%d", &number);
li $v0, 5 # call code for read_int
syscall # run the read_int syscall
move $t0, $v0 # store input in $t0
move $a0, $t0 # move input to argument register $a0
addi $sp, $sp, -12 # move stackpointer up 3 words
sw $t0, 0($sp) # store input in top of stack
sw $ra, 8($sp) # store counter at bottom of stack
jal factorial # call factorial
# when we get here, we have the final return value in 4($sp)
lw $s0, 4($sp) # load final return val into $s0
# printf("The value of 'factorial(%d)' is: %d\n",
la $t1, msgres1 # load msgres1 address into $t1
lw $a0, 0($t1) # load msgres1_data value into $a0
li $v0, 4 # system call for print_string
syscall # print value of msgres1_data to screen
lw $a0, 0($sp) # load original value into $a0
li $v0, 1 # system call for print_int
syscall # print original value to screen
la $t2, msgres2 #load msgres2 address into $t1
lw $a0, 0($t2) # load msgres_data value into $a0
li $v0, 4 # system call for print_string
syscall # print value of msgres2_data to screen
move $a0, $s0 # move final return value from $s0 to $a0 for return
li $v0, 1 # system call for print_int
syscall # print final return value to screen
addi $sp, $sp, 12 # move stack pointer back down where we started
# return 0;
li $v0, 10 # system call for exit
syscall # exit!
.text
factorial:
# base case - still in parent's stack segment
lw $t0, 0($sp) # load input from top of stack into register $t0
#if (x == 0)
beq $t0, 0, returnOne # if $t0 is equal to 0, branch to returnOne
addi $t0, $t0, -1 # subtract 1 from $t0 if not equal to 0
# recursive case - move to this call's stack segment
addi $sp, $sp, -12 # move stack pointer up 3 words
sw $t0, 0($sp) # store current working number into the top of the stack segment
sw $ra, 8($sp) # store counter at bottom of stack segment
jal factorial # recursive call
# if we get here, then we have the child return value in 4($sp)
lw $ra, 8($sp) # load this call's $ra again(we just got back from a jump)
lw $t1, 4($sp) # load child's return value into $t1
lw $t2, 12($sp) # load parent's start value into $t2
# return x * factorial(x-1); (not the return statement, but the multiplication)
mul $t3, $t1, $t2 # multiply child's return value by parent's working value, store in $t3.
sw $t3, 16($sp) # take result(in $t3), store in parent's return value.
addi $sp, $sp, 12 # move stackpointer back down for the parent call
jr $ra # jump to parent call
.text
#return 1;
returnOne:
li $t0, 1 # load 1 into register $t0
sw $t0, 4($sp) # store 1 into the parent's return value register
jr $ra # jump to parent call
@ferdinice
Copy link

that is kul, can I please have a complete tutorial for dummies on Assemble Language Programming

@matha4ster
Copy link

It works for any number smaller than 13 but doesnot work for anything greater than 13.
Can you please let us know how to handle the issue for larger number?

@honda707
Copy link

thank you so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment