这是一个汇编语言问题。我已经想出了如何接受用户输入作为字符串并将其转换为整数
将当前总和乘以 10(移动 3 并向左移动 1 个位置,然后将两个结果相加)并从字符串中添加新数字(已通过减去 48 转换为数字)
现在直到溢出点这都可以正常工作,但是如何将数字拆分以适合两个寄存器?它必须被划分或移位吗?请详细解释!
为此,您将需要合成双宽度操作,即移位和加法。
对于移位,除了分别移位两半之外,您还需要将溢出的高位从低半部分带入高半部分。为此,您酌情将低半部分向右移动,然后使用按位OR
或加法将它们放入高半部分。
在伪代码中(使用逻辑移位):
result_low = (orig_low << n)
result_high = (orig_high << n) | (orig low >> (32 - n))
对于加法,您处理低半部分,然后检查它是否小于原始操作数之一。如果是,则意味着发生了溢出,您必须将进位添加到加数的高半部分和高半部分。
result_low = op1_low + op2_low
result_high = op1_high + op2_high + ((result_low < op1_low) ? 1 : 0)
一个可能的 asm 实现:
la $t2, buff ; pointer to string
li $t0, 0 ; low
li $t1, 0 ; high
loop:
lb $t3, ($t2) ; load next byte
beq $t3, $zero, done ; end of string?
addi $t3, $t3, -48 ; convert from ascii
; t4,5 = t0,1 << 1
srl $t6, $t0, 31 ; t6 is used for the spilled bit
sll $t4, $t0, 1 ; shift low half
sll $t5, $t1, 1 ; shift high half
or $t5, $t5, $t6 ; put in the spilled bit
; t0,1 <<= 3
srl $t6, $t0, 29 ; the 3 spilled bits
sll $t0, $t0, 3 ; shift low half
sll $t1, $t1, 3 ; shift high half
or $t1, $t1, $t6 ; put in the spilled bits
; t0,1 += t4,5
addu $t0, $t0, $t4 ; add low halves
addu $t1, $t1, $t5 ; add high halves
sltu $t6, $t0, $t4 ; t6 = (t0 < t4), that is the carry
addu $t1, $t1, $t6 ; add the carry if any
; ok t0,1 has been multiplied by 10
addu $t0, $t0, $t3 ; just add the digit now
sltu $t6, $t0, $t3 ; the carry
addu $t1, $t1, $t6 ; add the carry if any
addiu $t2, $t2, 1 ; increment pointer
b loop ; and continue
done:
您当然也可以直接使用乘法而不是移位。
数字是位移的。您可以参考 wiki 上给出的乘法序列来了解如何填充 LO 和 HI 寄存器
LO = (($s * $t) << 32) >> 32;
HI = ($s * $t) >> 32;