1

I was having troubles today with MIPS.

I wanted to do something clever, and re-write this complex if-statement:

if (c >= 'A' && c <= 'Z')

as

if ((unsigned) (c-'A') <= ('Z'-'A'))

Here's C that works as I expect:

#include <stdio.h>

int main(void) {
  char c = ',';
  if ((unsigned) c - 'A' <= 0) {
    putchar('~');
  }
  putchar('.');
  return 0;
}

How do I write that in MIPS?


My attempt doesn't work as I'd expect.

It looks like MIPS thinks that (unsigned) 44 - 65 (for example) is less than 0.

Here's a Minimal, Complete, and Verifiable example of my problem:

        .text
        .globl main

main:
        li $a0, ','
        subu $a0, $a0, 'A'
        ble $a0, $0, LESS
        j END
LESS:
        li $a0, '~'
        li $v0, 11
        syscall
        j END
END:
        li $a0, '.'
        li $v0, 11
        syscall
        li $v0, 10
        syscall

I expect it to output only ., because after

li $a0, ','
subu $a0, $a0, 'A'

I expect $a0 to contain some large positive integer (I thought subu was unsigned subtraction?).

But the ble $a0, $0, LESS branches, proving that apparently the unsigned ',' - 'A' (or 44 - 65) is less than 0.


How do I get this to not branch:

li $a0, ','
subu $a0, $a0, 'A'
ble $a0, $0, LESS

and this to branch:

li $a0, 'B'
subu $a0, $a0, 'A'
ble $a0, $0, LESS
theonlygusti
  • 11,032
  • 11
  • 64
  • 119
  • 1
    `ble` is a signed compare-and-branch. Use the `bleu` pseudo-instruction if it exists, or `sltu` / bnez. http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html. – Peter Cordes Oct 22 '18 at 22:06
  • @PeterCordes Thank you, that actually makes a lot of sense. How would `sltu` help me out? – theonlygusti Oct 22 '18 at 22:08
  • 1
    Also note that `x <= 0` as an unsigned compare doesn't make sense; it's always true. You want unsigned `c - 'A' <= 'Z'-'A'` to check for digits, like in [How to access a char array and change lower case letters to upper case, and vice versa](https://stackoverflow.com/a/35936844). (MIPS doesn't have flags, and its compare-and-branch instructions are limited, so it uses set on less-than unsigned to compare into an integer register which you then branch on. Look at optimized C compiler output on https://godbolt.org/ for MIPS which doesn't use pseudo-instructions) – Peter Cordes Oct 22 '18 at 22:09
  • @PeterCordes you're right. In my real code that's what I'm doing, but here I was just experimenting with my problem trying to re-work it into a Minimal, Complete, and Verifiable example. – theonlygusti Oct 22 '18 at 22:10
  • 1
    The unsignedness of `subu` just means it does not raise an exception, apart from that it does the same thing as `sub`. It doesn't give a "type" to the result or anything like that, assembly isn't C. – harold Oct 22 '18 at 22:13

0 Answers0