2

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
Craig Estey
  • 30,627
  • 4
  • 24
  • 48

1 Answers1

1

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
Craig Estey
  • 30,627
  • 4
  • 24
  • 48