MIPS hermite stack example use - recursion

I'm stuck on a stack. I have to call to a function in mips-32 assembly code, in which I have to evaluate a Hermite polynomial just by giving the n and the x as parameters. It must be done using recursion.
I've tried to set 2 base cases H0 and H1, using them both at the same time, but I can't identify the sequence and the pile draw that makes the code clear.
Follows the code:
li $t2,2
recursive_hermite: #H(n,x,___,___)
bge $a0,$t5,more_than_2
#### base
#### case
jr $ra ##<--- this takes us to the operation of the value
more_than_2:
## here you are supposed to store the values on stack
## (such as return address and n values)
addi $a0,$a0,-1 ##you must decrease n (or increase I'm not sure)
jal recursive_hermite ##once they are stored, you just recall
### operations of value
## $f12 must contain the whole value
jr $ra ####this one returns to the main
Does anyone know how to solve this problem?

I see you are in trouble. Judging the way you wrote the question it seems like your assigment is due tomorrow, so we have to work things fast.
You remind me of myself 20 years back, good old times when c++ was just being born and assembly was all the rage. I have heard of those cringy MIPS emulators like QTspim, you should avoid them and work like a real man with some real handy hardware.
Here is my tip: you have to store the partial results of the polinomials tested in every recursion. To do that you have to control time and space, which have to be perfectly balanced like all things should be.
If I was you I would start working in your step by step execution of the program so you can check what the register values are.
It is dangerous to go alone, take this:
.data
#COMPUTER PRINCIPLES UNIVERSITY OF MACANDCHESTER
#PRACTIC 5: HERMITE POLINOMYALS CALCULUS
#JACK ROBERTS II
userInput: .space 700
empty: .asciiz "Input is empty."
long: .asciiz "Input is too long."
invalid: .asciiz "Invalid base-33 number."
.text
ErrorLong:
#prints message for input that is too long
la $a0, long
li $v0, 4
syscall
j end
ErrorInvalid:
#prints message for invalid input
la $a0, invalid
li $v0, 4
syscall
j end
ErrorEmpty:
#prints message for empty string
la $a0, empty
li $v0, 4
syscall
j end
.globl main
main:
li $v0, 8
la $a0, userInput
li $a1, 200
syscall
Rid:
#takes care of leading spaces
li $t9, 32 # space
lb $t8, 0($a0)
beq $t9, $t8, Character
move $t8, $a0
j length
Character:
addi $a0, $a0, 1
j Rid
#takes care of length
length:
addi $t0, $t0, 0
addi $t1, $t1, 10
add $t2, $t2, $a0
#itertates through the array
traverse:
lb $s2, 0($a0)
beqz $s2, discovered
beq $s2, $t1, discovered
addi $a0, $a0, 1
addi $t0, $t0, 1
j traverse
#busted empty space or input that violates limit
discovered:
#if it's empty go to case for empty which outputs
beqz $t0, ErrorEmpty
slti $t4, $t0, 5
#if it's too long, go to case for too long and print
beqz $t4, ErrorLong
move $a0, $t2
#go to next verification process
j verify
#Comenzamos a calcular H0
verify:
lb $s3, 0($a0) #loads address here
beqz $s3, initial
beq $s3, $t1, initial
slti $t3, $s3, 48 #invalid for anything below 0
bne $t3, $zero, ErrorInvalid
slti $t3, $s3, 58 #legal input for everything less than or equal to 9
bne $t3, $zero, Move
slti $t3, $s3, 65 #legal input for everything less than or equal to 65, 'a'
bne $t3, $zero, Move
slti $t3, $s3, 88 #legal input for anything less than or equal to 88
bne $t3, $zero, Move
slti $t3, $s3, 97 # invalid input, not numerical nor alphabetical
bne $t3, $zero, ErrorInvalid
slti $t3, $s3, 120 #legal input for lower case characters
bne $t3, $zero, Move
bgt $s3, 119, ErrorInvalid # illegal input, out of range
#now I iterate again, this time to check for invalid input
Move:
addi $a0, $a0, 1 #iterates
j verify #goes to verification point
#first step of conversion, does the prerequisite work for translation
initial:
move $a0, $t2 #moves content
addi $t5, $t5, 0 #$t5 has 0 now
add $s0, $s0, $t0
addi $s0, $s0, -1 #decrement
#aqui empieza lo bueno
Must:
addi $sp, $sp, -16
sw $ra, 0($sp)
sw $ra, 4($sp)
sw $ra, 8($sp)
sw $ra, 12($sp)
jal Must
ExitMust:
lw $ra,16($sp)
lw $s4, 3($sp)
lw $s5, 2($sp)
lw $s6, 1($sp)
lw $s1, 0($sp)
jr $ra #return
#li $s4, 3 #each digit
#li $s5, 2
#li $s6, 1
#li $s1, 0
translate:
lb $s7, 0($a0) #loads digits
beqz $s7, final #final conversion step
beq $s7, $t1, final #if branch statement is true, move to final conversion statement
slti $t3, $s7, 58 #checks for less than or equal to 58
bne $t3, $zero, Base #OK to move forward if $t3 is not null
slti $t3, $s7, 88 #max for upper
bne $t3, $zero, Mari #OK to go to conversion of upper characters if $t3 is not null
slti $t3, $s7, 120 #max for lower
bne $t3, $zero, Mici #OK to go to conversion of lower characters if $t3 is not null
Base:
addi $s7, $s7, -48 #conversion for regular numbers
j row
Mari:
addi $s7, $s7, -55 #conversion for upper case
j row
Mici:
addi $s7, $s7, -87 #conversion for lower case
row: #determines which digit needs to be converted
beq $s0, $s4, one
beq $s0, $s5, two
beq $s0, $s6, three
beq $s0, $s1, last
#first character
one:
li $t6, 35937 #values to multiply by for the power of 3
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $a0, $a0, 1
j translate
#second character
two:
li $t6, 1089 #values to multiply by for the power of 2
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $a0, $a0, 1
j translate
#third character
three:
li $t6, 33 #values to multiply by for the power of 1
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $a0, $a0, 1
j translate
#fourth character
last:
li $t6, 1 #values to multiply by for the power of 0
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
#no more need to go back to translation step
final: #final step
li $v0, 1
move $a0, $t5 #moves content to $a0 so it can be printed
syscall
#last system call of the program will end program
end: #prints result
li $v0, 10
Hope it helps, if you need, ask for further explanation here, its been directly
taken out of my Final grade Work, and in my Masters.
PD: It is licensed under the GPL, so be careful on what you do with it, FBI might be looking for you.
Love :)

Related

Hexadecimal to decimal in MIPS. I'm getting really strange and negative output from $s3 could really use some help for I am all out of ideas

Been trying to write this hex to decimal converter in MIPS. Should take in up to 8 arguments (string) from command line, all hex starting with "0x", 4 bytes long and terminated with null character after every argument.
$s1= number of args; $s0-->args(0).
For these Program Arguments: 0x1A 0xF1 0x0B3:
.data
buffer: .space 32
args: .asciiz "\nProgram arguments:\n"
space: .asciiz " "
d_rep: .asciiz "\n\nInteger values:\n"
newLine: .asciiz "\n"
maxVal: .asciiz "Maximum value:\n"
.text
main:
add $t9, $zero, $zero # t9 will be max value
add $s1, $a0, $0 # store number of program arguments
add $s2, $a1, $0 # store address of where program arguments are
addi $s0, $0, 0 # use s0 as index for looping
addi $s7, $zero, 0 # used as index for print loop
add $s6, $s1, $0 # store numArgs for printloop
add $s5, $s2, $0 # store address for printloop
addi $t5, $zero, 16
addi $t6, $zero, 0
la $a0, args # load and print "Program arguments" string
li $v0, 4 # print
syscall
printloop:
beq $s7, $s6, printInt # only print as many times as there are args
lw $a0, 0($s5) # get the first word
li $v0, 4 # print
syscall
la $a0, space # print a space between words
li $v0, 4 # print
syscall
addi $s5, $s5, 4 # increment to next word
addi $s7, $s7, 1 # increment printloop counter
j printloop # loop again if there are more args
printInt:
la $a0, d_rep # print "Decimal values:"
li $v0, 4 # print
syscall
while:
beq $s0, $s1, done # while $s0 <= numArgs
lb $t1, 2($s2) # load s2[2] into
addu $t2, $zero, $t1 # make a copy so we dont lose place
subiu $sp, $sp, 4
convert:
beqz $t2, postConv # while t2 != null
blt $t2, 65, convNumber # if less than value of A then got a num
subiu $t3, $t2, 0x37 # -55 for uppercase letter
sll $t3, $t3, 4 # sll by 4 is same as mult by 16
sw $t3, ($sp) # store word to do some addition
addiu $t2, $t2, 1 # increment t2
subiu $sp, $sp, 4 # increment sp
j convert # go back to convert
convNumber:
addu $t3, $zero, $t2 # put t2 into t3 for to do some math
subiu $t3, $t3, 0x30 # -48 for number
sll $t3, $t3, 4 # sll by 4 is same as mult by 16
sw $t3, ($sp)
addiu $t2, $t2, 1 # increment t1
addiu $sp, $sp, 4 # increment sp
j convert # jump back to convert
postConv:
addi $sp, $sp, 4 # load the second value
lw $s4, ($sp) # load the first value
addi $sp, $sp, 4
# sll $s4, $s4, 4
lw $s3 ($sp)
addu $s3, $s3, $s4 # add em up for converted decimal
move $a0, $s3 # move to a0 so they pint
li $v0, 1 # print
syscall
addiu $s0, $s0, 1 # increment loop counter
addiu $s2, $s2, 4 # increment to next word
ble $t9, $t6, newMax # check for a new max value
j while # jump back to loop
newMax:
addu $t9, $zero, $t6 # got a new max so save it
j while
done:
la, $a0, newLine
li $v0, 4
syscall
la, $a0, newLine
li $v0, 4
syscall
la, $a0, maxVal
li $v0, 4
syscall
move $a0, $t9
li $v0, 1
syscall
la, $a0, newLine
li $v0, 4
syscall
li $v0, 10 # end program
syscall
My output is this:
Program arguments:
0x1A 0xF1 0x0B3
Integer values:
-2121474836290
Maximum value:
0
-- program is finished running --
But it should be : 26 241 179. And maxValue should be: 241
I would be very grateful if someone could help me debug this. Thank you! :D
You should be able to debug this yourself.  Single stepping the code to find this error is trivial.  If you don't know how to debug code, then suggest you focus on learning that.  Check each instruction to make sure it is doing what you expect, and if not, that's where the problem is.
argv is a pointer to pointers to characters — if we consider that a pointer to characters is a string, then we can describe argv as a pointer to strings.  To get single character from argv we have to choose which of the strings, then choose a character from that string.
You are doing this correctly when printing the program arguments, but are not following that approach for accessing their bytes, instead you're accessing individual bytes from the pointers themselves, which of course makes no sense.  Put another way, you're missing an indirection aka dereference.
This kind of error should stand out to you like a flashing warning sign when you single step over the lb $t1, 2($s2) instruction — because you are expecting it to fetch the ascii 1, 0x31, but are getting an 0xff instead.  When you see that an instruction is not getting what you expect that's where and when to rethink things: it is doing what you told it to do but you can observe that is not what you want.

MIPS where to put recursive calls in a palindrome problem

I am writing a program that accepts a user given strings and will output 1 if it is a palindrome or 0 if it isn't. It has to use recursion, however I am having trouble figuring out how to format the jal and jr statements so that recursion works properly.
main:
la $a0, askForString #simple text asking for user input
li $v0, 4
syscall
li $v0, 8
la $a0, userInput #points a0 to space allocated to get user input
li $a1, 41 #allows the user to enter input up to 40 characters
syscall
la $a0, userInput
li $v0, 4
syscall
lw $s0, userInput
j palindrome
palindrome:
la $a1, userInput
addu $a1,$a1,$s1
lbu $a0,($a1) # read the character in $s1 spot of the user inputted word
addi $sp, $sp, -4
sw $a0, 0($sp) #add the specific character to the stack so it can be looked at later
addi $s1, $s1, 1 #advance the count to look at the next character
jal palindrome
lw $t0, 0($sp) #load the last letter of the user given word from the stack
addi $sp, $sp, 4
la $a1, userInput
addu $a1,$a1,$s2
lbu $a0,($a1) # read the character in $s2 spot of the user inputted word
addi $s2, $s2, 1 #advance the count to look at the next character
bne $a0, $t0, fail #if the letters are not equal, print 0, not a palindrome
jr $ra
success:
la $a0, '1'
li $v0, 11
syscall
j end
fail:
la $a0, '0'
li $v0, 11
syscall
j end
end:
li $v0, 10 #op code to exit the program
syscall
I know the palindrome part of the program almost definitely does not work and has no way of knowing where the end of the word is, but if anyone could me with simply the recursion part that would be extremely helpful.

Double Recursion in Assembly works until secondary recursion becomes larger than the base case

I am trying to code a Assembly program that will ask for an integer and perform a recursive function: if n>5 f(n) = n*f(n-1)-f(n-3)+n-23 else n<=5 f(n)=15-2n I managed to get the first instance of recursion of the n*f(n-1)but when it goes for the second recursion of f(n-3) it performs the second portion improperly.
During the calculations, if I input 8 as the integer, the result should be 20 which I get but, when I input anything greater than 8 because then the second recursion hits an integer larger than 5 (the base case) I get an incorrect answer. Basically any input larger than 8 doesn't work
For example the correct answers are:
f(9) = 162
f(10) = 1602
f(11) = 17590
The answers I get
f(9)= 27
f(10)=22
f(11)=23
Here is my code:
```#data declarations: declare variable names used in program, storage allocated in RAM
.data
prompt1: .asciiz "\nEnter an Integer:\n" #Ending Index
message1: .asciiz "\nThe Solution is:\n"
answer: .word 0
#program code is contained below under .text
.text
.globl main #define a global function main
# the program begins execution at main()
main:
la $a0, prompt1 #load address of prompt1
li $v0, 4 #prepare print string
syscall
li $v0, 5 #prepare receive int
syscall
move $a0, $v0
addi $sp, $sp, -4
sw $ra, 0($sp)
jal Function
sw $v0, answer #move returned answer to a new memory
lw $ra, 0($sp)
addi $sp, $sp, 4
la $a0, message1 #load address of message1
li $v0, 4 #prepare print string
syscall
lw $a0, answer
li $v0, 1
syscall
jr $ra
############################################################################
# Procedure/Function Function1
# Description: recursive math function
# parameters: $a0 = value of n,
# return value: $v0 = answer
# registers to be used: $s3 and $s4 will be used.
############################################################################
Function:
addi $sp, $sp, -12 #adjust stack pointer
sw $ra, 8($sp) #save return address
sw $a0, 4($sp) #save n
sw $s0, 0($sp) #save immediate value (used for storing function(n-1))
li $t2, 15
slti $t0, $a0, 6
beq $t0, $zero, GreaterThanFive
LessThanFive:
add $t1, $a0, $zero
add $t1, $t1, $a0
sub $t2, $t2, $t1
move $v0, $t2
j Conclusion
GreaterThanFive:
addi $a0, $a0, -1
jal Function
move $s0, $v0
lw $a0, 4($sp)
addi $a0, $a0, -3
jal Function
lw $a0, 4($sp)
mul $t3, $a0, $s0
sub $t4, $t3, $v0
add $t5, $t4, $a0
addi $t6, $t5, -23
move $v0, $t6
Conclusion:
lw $s1,0($sp) # restore intermediate value
lw $a0,4($sp)
lw $ra,8($sp)
addi $sp,$sp,12 # restore stack
jr $ra #return to caller```

MIPS code using stack produces a recursion error

In this assignment I have to convert any given number from base 33 (1-9, A-W, and a-w) to base 10. If the input is empty, the message "Input is empty" is displayed. If input is anything else than numbers or letters A-W, output will be: "Input is invalid". This program must use stack and recursion.
I wrote my program without stack and it was working. I am now trying to transfer that into a program that uses stack but am getting the message "Input is empty", regardless of what I input.
Here is my MIPS code:
############### Base 33 to Base 10 Converter ###################
.data
userInput: .space 700
empty: .asciiz "Input is empty."
long: .asciiz "Input is too long."
invalid: .asciiz "Invalid base-33 number."
.text
ErrorLong:
#prints message for input that is too long
la $a0, long
li $v0, 4
syscall
j end
ErrorInvalid:
#prints message for invalid input
la $a0, invalid
li $v0, 4
syscall
j end
ErrorEmpty:
#prints message for empty string
la $a0, empty
li $v0, 4
syscall
j end
.globl main
main:
addi $sp, $sp, -16
li $v0, 8
la $a0, userInput
li $a1, 200
syscall
sw $a0, 0($sp) # put into stack the memory address where user input is
or $a0, $0, $0
sw $ra, 12($sp)
jal Number
lw $ra, 0($sp)
#TEST FOR END
#la $a0, strEnd
ori $a0, $a0, 4
syscall
#end
jr $ra
Number:
addi $sp,$sp,-4
lb $t8, 0($sp)
###################
Rid:
#takes care of leading spaces
li $t9, 32 # space
beq $t9, $t8, Character
move $t8, $a0 ############
j length
addi $sp,$sp,4
Character:
addi $a0, $a0, 1
j Rid
#takes care of length
length:
addi $t0, $t0, 0
addi $t1, $t1, 10
add $t2, $t2, $a0
addi $sp,$sp,-4
lb $s2, 0($sp)
#itertates through the array
traverse:
beqz $s2, discovered
beq $s2, $t1, discovered
addi $a0, $a0, 1
addi $t0, $t0, 1
j traverse
addi $sp,$sp,4
#busted empty space or input that violates limit
discovered:
#if it's empty go to case for empty which outputs
beqz $t0, ErrorEmpty
slti $t4, $t0, 5
#if it's too long, go to case for too long and print
beqz $t4, ErrorLong
move $sp, $t2
#go to next verification process
j verify
addi $sp,$sp,-4
lb $s3, 0($sp) #loads address here
#checks inputs
verify:
beqz $s3, initial
beq $s3, $t1, initial
slti $t3, $s3, 48 #invalid for anything below 0
bne $t3, $zero, ErrorInvalid
slti $t3, $s3, 58 #legal input for everything less than or equal to 9
bne $t3, $zero, Move
slti $t3, $s3, 65 #legal input for everything less than or equal to 65, 'a'
bne $t3, $zero, Move
slti $t3, $s3, 88 #legal input for anything less than or equal to 88
bne $t3, $zero, Move
slti $t3, $s3, 97 # invalid input, not numerical nor alphabetical
bne $t3, $zero, ErrorInvalid
slti $t3, $s3, 120 #legal input for lower case characters
bne $t3, $zero, Move
bgt $s3, 119, ErrorInvalid # illegal input, out of range
addi $sp,$sp,4
#now I iterate again, this time to check for invalid input
Move:
addi $sp, $sp, 1 #iterates
j verify #goes to verification point
#first step of conversion, does the prerequisite work for translation
initial:
move $a0, $t2 #moves content
addi $t5, $t5, 0 #$t5 has 0 now
add $s0, $s0, $t0
addi $s0, $s0, -1 #decrement
#load immediate puts values in registers to be used
li $s4, 3 #each digit
li $s5, 2
li $s6, 1
li $s1, 0
translate:
addi $sp,$sp,-4
lb $s7, 0($sp) #loads digits
beqz $s7, final #final conversion step
beq $s7, $t1, final #if branch statement is true, move to final conversion statement
slti $t3, $s7, 58 #checks for less than or equal to 58
bne $t3, $zero, Base #OK to move forward if $t3 is not null
slti $t3, $s7, 88 #max for upper
bne $t3, $zero, Mari #OK to go to conversion of upper characters if $t3 is not null
slti $t3, $s7, 120 #max for lower
bne $t3, $zero, Mici #OK to go to conversion of lower characters if $t3 is not null
addi $sp,$sp,4
Base:
addi $s7, $s7, -48 #conversion for regular numbers
j row
Mari:
addi $s7, $s7, -55 #conversion for upper case
j row
Mici:
addi $s7, $s7, -87 #conversion for lower case
row: #determines which digit needs to be converted
beq $s0, $s4, one
beq $s0, $s5, two
beq $s0, $s6, three
beq $s0, $s1, last
#first character
one:
li $t6, 35937 #values to multiply by for the power of 3
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $sp, $sp, 1 ####################
j translate
#second character
two:
li $t6, 1089 #values to multiply by for the power of 2
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $sp, $sp, 1 ###################
j translate
#third character
three:
li $t6, 33 #values to multiply by for the power of 1
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
addi $s0, $s0, -1
addi $sp, $sp, 1
j translate
#fourth character
last:
li $t6, 1 #values to multiply by for the power of 0
mult $s7, $t6
mflo $t7
add $t5, $t5, $t7
#no more need to go back to translation step
final: #final step
li $v0, 1
move $sp, $t5 #moves content to $a0 so it can be printed
syscall
#last system call of the program will end program
end: #prints result
li $v0, 10
syscall
jr $ra
In main, you save a0 (the user entered number) to 0(SP), and ra to 12(SP), then call Number.
In number, you add -4 to SP.
Ten attempt to get a byte from 0(SP)
I am assuming you are trying to get the first character from the user string ?
Since you added -4 to the stack, the a0 value you saved in 0(SP) is not at 4(sp).
The value you saved is the pointer to the string, so doing a load byte from the pointer:
So change:
lb $t8, 0($sp)
to
lw $a0, 4($sp)
lb $t8, 0($a0)
Which also means you don't need the move $t8, $a0 a couple of lines later

Error in MIPS assembler regarding fetch address not being aligned

having some trouble with an assignment, not looking for solution code, just some answers to why I keep encountering this error.
The program asks the user for 10 digits and then displays the resulting sum (using the stack and recursion).
I know from debugging that the read: portion works fine, but I get the error "Runtime exception at 0x0040005c: fetch address not aligned on word boundary 0x00000001". The error refers to the line in summation: lw $t0, 0($a0)
Not sure what is wrong since I only ever increment by 4 bytes. I've checked other similar questions but couldn't find any clarification. Any help would be greatly appreciated.
.data
A1: .space 40
input: .asciiz "please enter a number: "
Str: .asciiz "the sum is: "
.text
main:
li $s1, 0
la $t0, A1
addi $s0, $zero, 0
read:
beq $s1, 10, prep
li $v0, 4
la $a0, input
syscall
li $v0, 5
syscall
sw $v0, ($t0)
addi $t0, $t0, 4
addi $s1, $s1, 1
j read
prep:
la $a0, A1
addi $a1, $a0, 40
jal summation
summation:
subi $sp, $sp, 8
sw $ra, 4($sp)
lw $t0, 0($a0)
sw $t0, 0($sp)
sgt $t1, $a0, $a1
beq $t1, $zero, L1
addi $v0, $zero, 0
addi $sp, $sp, 8
jr $ra
L1:
addi $a0, $a0, 4
jal summation
lw $a0, 0($sp)
lw $ra 4($sp)
addi $sp, $sp, 8
add $v0, $a0, $v0
jr $ra

Resources