0

How do I write a program to convert lowercase letters in MIPS to uppercase, leaving the others untouched?

I know that I will have to subtract 32 from the ASCII code of lowercase characters to convert them to their corresponding uppercase characters.

1 Answers1

2

Code with explanation:

.data
    buffer: .space 100
    str1:  .asciiz "Enter string: "
    str2:  .asciiz "Capitalized: "

.text

main:
    la $a0, str1    # Load and print string asking for string
    li $v0, 4
    syscall

    li $v0, 8       # take in input
    la $a0, buffer  # load byte space into address
    li $a1, 100      # allot the byte space for string
    syscall
    move $s0, $a0   # save string to s0

    li $v0, 4
    li $t0, 0

    #Loop to capitalize
    loop:
    lb $t1, buffer($t0)    #Load byte from 't0'th position in buffer into $t1
    beq $t1, 0, exit       #If ends, exit
    blt $t1, 'a', not_lower  #If less than a, exit
    bgt $t1, 'z', not_lower #If greater than z, exit
    sub $t1, $t1, 32  #If lowercase, then subtract 32
    sb $t1, buffer($t0)  #Store it back to 't0'th position in buffer

    #if not lower, then increment $t0 and continue
    not_lower: 
    addi $t0, $t0, 1
    j loop

    exit:
    la $a0, str2    # load and print "capitalized" string
    li $v0, 4
    syscall

    move $a0, $s0   # primary address = s0 address (load pointer)
    li $v0, 4       # print string
    syscall
    li $v0, 10      # end program
    syscall
  • There's a trick for range-checks: `(c-'a') <= ('z'-'a')` (unsigned compare) is true only for lower-case letters, and false for everything else (including `0`). Integers below `'a'` wrap to an unsigned value above 25. You still need to check separately for `0` to exit the loop, but you can combine both other branches into a sub / branch. (Doesn't save any instructions on a MIPS simulator, but on a real MIPS with a branch-delay slot it's still actually useful for code size as well as fewer branch mispredicts). – Peter Cordes Oct 31 '17 at 07:08
  • It's a lot more useful on a machine like x86 where cmp / jcc are separate instructions, so two compares against separate numbers requires 4 total instructions. But the main advantage is fewer conditional branches for the CPU to predict; the execution path is the same whether the character is above or below the lower-case-ASCII range. – Peter Cordes Oct 31 '17 at 07:09
  • 1
    Also BTW, *if* you know your inputs are already alphabetic, you can just `AND` with `~0x20` to mask off that bit, leaving upper-case letters untouched but lower case letters changed to uppercase. (XOR to flip case, OR to force to lowercase.) For an x86 example of all of these tricks, see [flip case of alphabetic characters, leaving others untouched](https://stackoverflow.com/a/35936844/224132), including a SIMD vectorized version with SSE2 – Peter Cordes Oct 31 '17 at 07:14
  • Oh, actually the sub/unsigned compare trick is useful: `blt` with `'a'` is only a pseudo-instruction. [MIPS hardware only has compare-and-branch with registers, not immediate](http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html), so that would have to assemble to `slti $at, $t1, 'a'` / `bne $at, $0, not_lower` or similar. – Peter Cordes Oct 31 '17 at 07:22