-1

我正在尝试将语句if(isalpha(c))(其中c是 char 变量)从 C++ 转换为 MIPS 程序集。我试图用谷歌搜索它,但我找不到答案。有人有什么主意吗?谢谢你的时间。

4

1 回答 1

1

I'm just going to demonstrate one possible way, which is not efficient or "cool", but it's simple.

So, you want an equivalent of this C block:

if (isalpha(c))
{
    /* Do stuff... */
}

Which is like this, considering how isalpha() works:

if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
{
    /* Do stuff... */
}

But there are no "block" structures in assembly. Everything is a jump (or a goto in C, which you should never use.) So, to get closer to the assembly version, we might modify our C code to use a jump:

if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
    goto AfterStuff;

/* Do stuff... */

AfterStuff:

Note that we are jumping over the "Do stuff" part if the reverse of our condition was true. Now, assuming we know that 'A' < 'Z' < 'a' < 'z' (the ASCII codes are, respectively: 65, 90, 97, 122,) then we can rewrite the above code like this:

if (c < 65)
    goto AfterStuff;
if (c <= 90)
    goto DoStuff;
if (c < 97)
    goto AfterStuff;
if (c > 122)
    goto AfterStuff;

DoStuff:
/* Do stuff... */

AfterStuff:

Note that if c is less than 'A', we jump after the stuff. But if after comparing c and 'A', we find out that c is not only greater or equal to 'A' (because we didn't jump away,) but it's also less than or equal to 'Z', we jump directly to the "stuff" and don't check anything else. Also, the operands of the last blt instruction are reversed.

The assembly gets a little complicated, because we have to load the required immediates into registers and whatnot. Here's the code:

  lb    $t0, ($s0)            # assuming address of c is in s0 register

  addi  $t1, $zero, 65        # set t1 = 'A'
  blt   $t0, $t1, AfterStuff  # if (c < 'A') goto AfterStuff

  addi  $t1, $zero, 90        # set t1 = 'Z'
  ble   $t0, $t1, DoStuff     # if (c <= 'Z') goto DoStuff

  addi  $t1, $zero, 97        # set t1 = 'a'
  blt   $t0, $t1, AfterStuff  # if (c < 'a') goto AfterStuff

  addi  $t1, $zero, 122       # set t1 = 'z'
  blt   $t1, $t0, AfterStuff  # if ('z' < c) goto AfterStuff

DoStuff:
  # Do whatever you want to do

AfterStuff:

I believe the above works, but I absolutely can't be sure. It has been more than a decade since I wrote any MIPS assembly code (or any other code for a MIPS) and I was never very proficient anyways.

于 2013-04-21T01:48:53.067 回答