Assembly 如何在MIPS中实现if(条件1和条件2)?

Assembly 如何在MIPS中实现if(条件1和条件2)?,assembly,mips,procedure,subroutine,Assembly,Mips,Procedure,Subroutine,我编写了以下函数来检查字符是否为数字: # IsDigit - tests a if a character a digit or not # arguments: # $a0 = character byte # return value: # $v0 = 1 - digit # 0 - not a digit IsDigit: lb $t0, ($a0) # obtain the character li $t1, 48 # '0' - ch

我编写了以下函数来检查字符是否为数字:

# IsDigit - tests a if a character a digit or not 
# arguments:
#   $a0 = character byte
# return value:
#   $v0 =   1 - digit
#           0 - not a digit
IsDigit:
    lb $t0, ($a0) # obtain the character
    li $t1, 48 # '0' - character
    li $t2, 57 # '9' - character
    bge $t0, $t1, condition1
condition1:
    ble $t0, $t2, condition2

    li $v0, 0
    j return

condition2:
    li $v0, 1

return:                                                                                 
    # return 
    jr $ra 
有没有更好的方法来写这个

编辑:以下是第2版

IsDigit:
    lb $t0, ($a0) # obtain the character
    li $t1, 48 # '0' - character
    li $t2, 57 # '9' - character
    bge $t0, $t1, condition1

    j zero

condition1: 

    ble $t0, $t2, condition2

zero:
    li $v0, 0
    j return

condition2:
    li $v0, 1
    j return

return:                                                                                 
    # return 
    jr $ra 
编辑-2:以下是第3版

IsDigit:
    lb $t0, ($a0) # obtain the character
    li $t1, 48 # '0' - character
    li $t2, 57 # '9' - character


    bge $t0, $t1, con1_fulfilled #bigger tha or equal to 0  
    j con1_not_fulfilled

con1_fulfilled:
    ble $t0, $t2, con2_fullfilled #less than or equal to 9
    j con2_not_fulfilled

con2_fullfilled:
    li $v0, 1
    j return

con1_not_fulfilled:
con2_not_fulfilled:
    li $v0, 0

return:                                                                     
    # return 
    jr $ra 

在一般情况下,您使用两个分支,它们通过
if()
主体到达。如果取其中一个,则
If
主体不运行。在汇编中,您通常希望使用C条件的否定,因为您跳过了循环体,所以它不会运行。您的较新版本会向后执行,因此还需要无条件的
j
指令,这使得您的代码更加复杂

(gt)相反。对于使用包含范围(le和ge)编写的C,使用相同数值的asm应在使用独占范围(排除
eq
ual情况)的相反条件下分支。或者,您可以调整常量和
bge$t0、'9'+1
或其他任何内容,这些内容在16位立即数的末尾非常有用

# this does assemble with MARS or clang, handling pseudo-instructions
# and I think it's correct.
IsDigit:
    lb  $t0, ($a0)    # obtain the character

    blt   $t0, '0', too_low    # if(   $t0 >= '0'  
    bgt   $t0, '9', too_high   #    && $t0 <= '9')
      # fall through into the if body
    li    $v0, 1
    jr    $ra                    # return 1

too_low:
too_high:                    # } else {
    li    $v0, 0

#end_of_else:
    jr    $ra                # return 0
火星的汇编程序拒绝立即汇编
-'0'
,您必须将其写成
-48
-0x30
。clang的汇编程序在添加$v0、$a0、'0'时没有问题


如果您编写
subiu$v0,$a0,'0'
,MARS将使用脑残的lui+ori构造
'0'
,因为它对于大多数汇编程序不支持的扩展伪指令来说非常简单。(MIPS没有
subi
指令,只有
addi
/
addiu
,两者都采用符号扩展立即执行。)

当然,因为转移到下一条无论如何都要执行的指令是毫无意义的。因此,
bge$t0,$t1,条件1
毫无意义。这应该返回0,但它不返回。@Jester,为什么要返回0?哦,好吧,这不是在检查它是否低于
'0'
我的错。转到下一条指令仍然是毫无意义的。它没有任何作用。如果为真,则转到条件1,如果为假。。。杰斯特,看第二版的编辑。看起来好多了。当然,您可以将
bge
反转为
blt
,这样您就不需要
jzero
。另外,您不需要在
condition2
中使用
j返回
,因为它就在后面。
zero
中的
j return
也可以直接替换为
jr$ra
,并删除
return
标签。还要注意的是,
isdigit
通常不接受指针,而且您的注释也没有提到任何关于指针的内容,因此
lb$t0,($a0)
非常可疑。很可能您已经在
$a0
中拥有该字符。
# IsDigit - tests a if a character a digit or not 
# arguments:
#   $a0 = character byte (must be zero-extended, or sign-extended which is the same thing for low ASCII bytes like '0'..'9')
# return value:
#   $v0 = boolean: 1 -> it is an ASCII decimal digit in [0-9]

IsDigit:
    addiu   $v0, $a0, -'0'            # wraps to a large unsigned value if below '0'
    sltiu   $v0, $v0, 10              # $v0 = bool($v0 < 10U)  (unsigned compare)
    jr      $ra