Commentaire : factoriel
Format du document : text/plain
Prévisualisation
.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