![](/img/trans.png)
[英]Mars MIPS Simulator 4.5 Locks up on User Input read-string syscall
[英]Verifying user input using syscall 8 in MIPS
我正在努力寻找一种有效的方法来检查用户是否输入了一个有效的输入,它只是数字 (0~9),使用 syscall 8
输入长度为 4 个字节(1 个字),
我需要检查每个字节(字符)是否是数字,
我想尝试运行一个循环并检查其 ascii 值是否低于 48('0' ascii 十进制值),
或高于 57('9' ascii 十进制值),
这是一种有效的方法吗?
如果是这样,在 MIPS 中实现这样的 if 语句的正确方法是什么?
例如
if (x < 48) or (x > 57) {...}
*注意:假设我确实有一个标志来知道在哪里停止循环
*编辑:这是一段代码,使其更清晰:
.data
number:
.word w1
.text
.globl main
main:
la $a0, number # read the number input from user
li $a1, 6 # buffer set to max of 4 bytes (32 bits),
# assuming the input is no more than the length of a word,
# + 2 reserved bytes
li $v0, 8
syscall
尝试这个:
lbu $t0, x # read next byte
sltiu $t1, $t0, 48 # t1 = (x < 48) ? 1 : 0
bnez $t1, fail
sltiu $t1, $t0, 58 # t1 = (x < 58) ? 1 : 0
beqz $t1, fail
# we now know that 48 <= $t1 <= 57
. . .
. . .
fail: # input byte was not a digit if we get to here
用于范围检查的无符号比较技巧在这里很好,只需使用 sub/sltiu/beq 即可完成工作,并为您提供 ASCII->整数数字值作为其中的一部分。
x86 示例。 就像检查字母字符一样,请参阅^= 32 背后的想法是什么,将小写字母转换为大写字母,反之亦然?
将字符(一个字节)零扩展或符号扩展到 32 位寄存器中; 任何一个都有效,因为 ASCII 0..9 数字范围是有符号的,并且此范围检查正确排除了所有其他 32 位数字。
# lbu $t0, x # for example
# ASCII character in $t0
addiu $t0, $t0, -0x30 # subtract '0' : range shift from '0'..'9' to 0..9
sltiu $t1, $t0, 10 # t1 = c < 10 unsigned
beqz $t1, non_digit # jump if c>=10
# fall through: it was a digit, 0..9 value in $t0
...
non_digit:
输入太低意味着t0 -= '0'
换行到一个大的无符号值。 输入太高意味着减去后它(无符号)大于9
。
如果您想保留原始字符值及其整数数字值(如果它是数字),请选择不同的寄存器。
不幸的是,MARS 不支持方便的 ASCII 字符常量作为数字表达式的一部分,因此它无法组合addiu $t0, $t0, -'0'
来减去'0'
。
你可以写sltiu
/ beqz
作为bgeu $t0, 10, non_digit
伪指令。
你可以写bgtu $t0, 9, non_digit
,但不要因为火星组装,为3个机器指令(包括addi
兑现9
的寄存器和sltu
两个REG之间),而不是2.您可以通过救不了任何东西在循环之前使用保存9
或10
设置的寄存器,或者: MIPS 分支条件仅与零比较,eq / ne 除外。 blt $t1, $t9, non_digit
也是伪指令。
在具有分支延迟槽的真实 MIPS 上,仅分支一次当然非常好。
您当然可以将其用作循环的循环条件,直到遇到非数字为止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.