问题描述
.text
.globl __start
__start:
li $t1,9
li $t2,7
addi $t1,$t1,3
addi $t2,$t2,3
li $t3,0xFFFFFFFF
srl $t3,$t3,$t1
sll $t3,$t2
srl $t3,$t2
not $t3,$t3
li $s1,0x12345678 # input data in $s1 register
and $s2,$s1,$t3 # output data in $s2 register
li $v0,10
syscall # exit
解决方法
看起来以not $t3,$t3
结尾的序列创建了一个AND掩码,其边沿为1位,而中间为零。因此,您可以执行相同的操作:先旋转中间的一端,然后将其移出,然后再旋转回去。
但是MIPS没有硬件旋转指令。 ror
和rol
只是伪指令,它们会移位两次并进行“或”运算,因此效率将更高。
创建和使用AND掩码 可能是将两个输入之间的位范围归零的最佳方法。但是您可能可以更有效地构造遮罩。类似于~((1<<high) - (1<<low))
或类似的东西,它需要一个li reg,1
,两个sllv
,一个subu
和一个not
。该表达式中可能有一个一一对应的内容。我没有检查,因为这不是您真正要问的。
或者当然,如果位的位置是已知的常数,则应该只在汇编时进行数学运算,并使用掩码运行一个li
。 (1或2条硬件指令,或者如果生成的掩码仅将低位设置为16,甚至是andi
。)一个好的汇编程序可以让您编写涉及常量的表达式并对其求值,例如li $t1,~((1<<9) - (1<<7))
。但是,例如MARS不允许您这样做。您必须对0xfffffe7f