I have already tried changing the adding more space to the stack and that didn't seem to help ro change anything also in the uppercase label function I initially had the register names as $s4, $s5, $s6 which I change to $s0, $s1, and $s2 respectively but for some reason that gave me some errors. Now when I run the code there is no errors but there is no output for some reason. Does anyone possibly have any idea as to why? Thank you in advance
C Code:
#include <stdio.h>
// global array
char str[] = "Homework-10";
// switch lowercase characters in str to uppercase
char
uppercase(char ch)
{
if ((ch >= 'a') && (ch <= 'z')) {
ch = ch - 32;
}
return ch;
}
int
main()
{
for (int i = 0; str[i] != '\0'; i++) {
str[i] = uppercase(str[i]);
}
printf("%s", str);
return 0;
}
High Level MIPS Assembly:
.data
str: .asciiz "Homework-10"
a: .byte 'a'
z: .byte 'z'
.text
main:
# adjust the stack pointer
addi $sp,$sp,-4
# save $ra on the stack
sw $ra,0($sp)
# str[] address
la $s0,str
FOR:
# str[] value
lb $s1,0($s0)
beq $s1,$0,DONE
move $a0,$s1
jal uppercase
move $s1,$v0 # save the return value in s1
# store the result back to str[i]
sb $s1,0($s0)
addi $s0,$s0,1
j FOR
DONE:
# print the modified string
la $a0,str
li $v0,4
syscall
# restore everything
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
uppercase:
# save the registers on the stack
addi $sp,$sp,-16
sw $ra,0($sp)
sw $s0,4($sp) # use this for a
sw $s1,8($sp) # use this for z
sw $s2,12($sp) # use this for ch
# ch argument
move $s2,$a0
# load 'a' and 'z'
lb $s0,a
lb $s1,z
# check if ch is a lowercase character
blt $s2,$s0,L1
bgt $s2,$s1,L1
# convert ch to uppercase
addi $s2,$s2,-32
L1:
# restores registers from the stack
lw $ra,0($sp)
lw $s0,4($sp) # use this for a
lw $s1,8($sp) # use this for z
lw $s2,12($sp) # use this for ch
addi $sp,$sp,16
move $v0,$s2 # return the converted character
jr $ra
You have a bug:
In uppercase
, at L1:
you restore the registers and then do: move $v0,$s2
(to set the return value for the function)
This sets $v0
to the caller's value of $s2
and not the value computed by uppercase
.
The result is that when the syscall
[to print] is executed, the str
array is all zeros (because caller's $s2
has zero in it).
To fix, move the move $v0,$s2
to the first statement following L1:
I ran this under mars
(vs. spim
), so this may be specific to mars
.
It printed the correct result, but, when the final jr $ra
is executed in main
, it jumps to location 0x00000000.
To fix this, I added an exit syscall instead
Here is the corrected code. It is annotated with the bugs and fixes:
.data
str: .asciiz "Homework-10"
a: .byte 'a'
z: .byte 'z'
.text
main:
# adjust the stack pointer
addi $sp,$sp,-4
# save $ra on the stack
sw $ra,0($sp)
# str[] address
la $s0,str
FOR:
# str[] value
lb $s1,0($s0)
beq $s1,$0,DONE
move $a0,$s1
jal uppercase
move $s1,$v0 # save the return value in s1
# store the result back to str[i]
sb $s1,0($s0)
addi $s0,$s0,1
j FOR
DONE:
# print the modified string
la $a0,str
li $v0,4
syscall
# NOTE/FIX: just exit here
li $v0,10
syscall
# restore everything
# NOTE/BUG: this just jumps to location 0
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
uppercase:
# save the registers on the stack
addi $sp,$sp,-16
sw $ra,0($sp)
sw $s0,4($sp) # use this for a
sw $s1,8($sp) # use this for z
sw $s2,12($sp) # use this for ch
# ch argument
move $s2,$a0
# load 'a' and 'z'
lb $s0,a
lb $s1,z
# check if ch is a lowercase character
blt $s2,$s0,L1
bgt $s2,$s1,L1
# convert ch to uppercase
addi $s2,$s2,-32
L1:
# NOTE/FIX: this is the correct place to set the return value
move $v0,$s2 # return the converted character
# restores registers from the stack
lw $ra,0($sp)
lw $s0,4($sp) # use this for a
lw $s1,8($sp) # use this for z
lw $s2,12($sp) # use this for ch
addi $sp,$sp,16
# NOTE/BUG: s2 holds the return value but it has been restored to _caller's_
# value -- this occurs too late
###move $v0,$s2 # return the converted character
jr $ra