首页 > 解决方案 > 用移位和循环寄存器替换“and”,结果和输入保持不变

问题描述

.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,$t3,$t1    
sll $t3,$t3,$t2   
srl $t3,$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

标签: assemblymipsmips64

解决方案


看起来以 结尾的序列not $t3,$t3创建了一个 AND 掩码,边缘为 1,中间为 0。所以你可以做同样的事情,通过旋转然后到一端,将它们移出,然后旋转回来来敲掉中间位。


但是 MIPS 没有硬件旋转指令。 ror并且rol只是移位两次和 OR 的伪指令,所以这不会更有效。

创建和使用 AND 掩码可能将两个输入之间的位范围归零的最佳方法。但是您可能可以更有效地构建掩码。像~((1<<high) - (1<<low))或类似的东西,它需要一li reg,1、二sllv、一subu和一not。该表达式中可能有一个非一的;我没有检查,因为这不是你真正要问的。

或者当然,如果位位置是已知的常量,您应该在汇编时进行数学运算并li使用掩码运行一个。(1 或 2 个硬件指令,或者甚至只是一个andi如果生成的掩码仅在低 16 位设置位。)一个好的汇编程序可以让您编写涉及常量的表达式并对其进行评估,例如li $t1, ~((1<<9) - (1<<7)). 但是例如,火星不允许你这样做。你必须硬编码0xfffffe7f


推荐阅读