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