5

I am new in MIPS, and I am trying to judge whether each char in a string is an alpha. I used the ASCII code to help me to judge it, while I found there is no instruction representing larger than meaning. So I try to implement a not operation from the instructions I have known. Here's part of my code:

isAlpha:
  sltiu $t0, $s2, 123
  sltiu $t1, $s2, 97
  nor $t1, $t1, $t1
  and $t0, $t0, $t1

  sltiu $t2, $s2, 107
  sltiu $t3, $s2, 81
  nor $t3, $t3, $t3
  and $t2, $t2, $t3

  or $t0, $t0, $t2

  bne $t0, $zero, countAlpha
  jr $ra

However, I could not get the result I want. I set a breakpoint and found that my not operation seems to have some problems: After judge

In my exception, $t1 should be 1 and $t2 should be 0, while the reality is not.

Where's the wrong place in my code? Is there any way to implement not operation in MIPS? Or is there a better way to implement larger than meaning in MIPS? Thanks in advance.

jianjieluo
  • 319
  • 1
  • 4
  • 15

2 Answers2

10

You have a not operation here:

nor $t1, $t1, $t1

Often you can just type the not mnemonic and your assembler will interpret it as a pseudo instruction

I think you want an exclusive or operation to tell you if your input is just one of less than 123 and less than 97.

Something like this (totally untested)

isAlpha:
  sltiu $t0, $s2, 123
  sltiu $t1, $s2, 97
  xor $t0, $t0, $t1

  sltiu $t2, $s2, 107
  sltiu $t3, $s2, 81
  xor $t2, $t2, $t3

  or $t0, $t0, $t2

  bne $t0, $zero, countAlpha
  jr $ra
sfi
  • 146
  • 1
  • 6
  • I created an answer for this, but before posting, I found yours. I was almost going to not post mine [which had an additional `and` instruction] because I came to think yours was sufficient--and upvote your's. Then, I realized the edge case I was worried about was real. But, +1 for you anyway. See my answer for the what/why – Craig Estey Mar 23 '17 at 00:38
  • 3
    @Craig Estey You say in your answer "xor of two zeros is 1", are you sure? – sfi Mar 23 '17 at 08:38
  • 1
    I guess I was sleep deprived that day :-) – Craig Estey Mar 23 '17 at 17:37
2

You can get the effect of gt by reversing the arguments to slt*:

    sltu   $v0,$t0,$t1             # v0 = $t0 < $t1 (what you have)
    sltu   $v0,$t1,$t0             # v0 = $t0 > $t1 (what you want)

Note that ge or le is a bit trickier. Consider the various branch pseudo ops like: blt, bge, bgt, bge [they generate slt* followed by either beq or bne]. They're usually easier to work with.

xor can do bitwise negation. The not pseudo-op will generate a nor.

Below is some code that does what you want. Note that it is similar to the code sfi posted, but has an additional [and necessary] and during the range check to prevent a false positive.

For example, without the and, the range check for a-z will report true on anything higher than z (e.g. 0x7B aka {). This is because both slt instructions will generate 0. But, xor of two zeros is 1. So, the xor result must be anded against the high range value slt result

# isAlpha -- decide if char is alpha
#
# RETURNS:
#   v0 -- 1=is alpha
#   s6 -- count of alpha chars
#
# arguments:
#   s2 -- character to test
#
# registers:
#   t0 -- holds lt 'a/A'? value
#   t1 -- holds lt 'a/A' + 1? value
#   t2 -- bool for within 'a-z'
#   t3 -- bool for within 'A-Z'
isAlpha:
    # within a-z range
    sltiu   $t0,$s2,0x61            # lt 'a'? (i.e. not a-z)
    sltiu   $t1,$s2,0x7B            # lt 'z' + 1? (i.e. le 'z')
    xor     $t2,$t0,$t1             # want one but not both
    and     $t2,$t2,$t1             # want only lt 'z' + 1

    # within A-Z range
    sltiu   $t0,$s2,0x41            # lt 'A'? (i.e. not A-Z)
    sltiu   $t1,$s2,0x5C            # lt 'Z' + 1? (i.e. le 'Z')
    xor     $t3,$t0,$t1             # want one but not both
    and     $t3,$t3,$t1             # want only lt 'Z' + 1

    or      $v0,$t2,$t3             # decide if alpha
    add     $s6,$s6,$v0             # increment alpha count
    jr      $ra
Craig Estey
  • 30,627
  • 4
  • 24
  • 48