我正在学习汇编代码,并且给定此代码,我需要找到此代码的内容。但是,我正在尝试使用QTSPIM进行调试。我知道每个寄存器内的值是多少,但我仍然不明白此代码是什么。
如果您找到了模式以及该代码的内容,您能告诉我如何做到这一点,以及在哪一行中知道该模式?谢谢!
.text
.globl main
.text
main:
li $s0, 0x00BEEF00 ##given $s0= 0x00BEEF00
Init:
li $t0, 0x55555555
li $t1,0x33333333
li $t2,0x0f0f0f0f
li $t3,0x00ff00ff
li $t4,0x0000ffff
Step1: and $s1, $s0, $t0
srl $s0,$s0,1
and $s2,$s0,$t0
add $s0,$s1,$s2
Step2: and $s1,$s0,$t1
srl $s0,$s0,2
and $s2,$s0,$t1
add $s0,$s1,$s2
Step3: and $s1,$s0,$t2
srl $s0,$s0,4
and $s2,$s0,$t2
add $s0,$s1,$s2
Step4: and $s1,$s0,$t3
srl $s0,$s0,8
and $s2,$s0,$t3
add $s0,$s1,$s2
Step5:
and $s1,$s0,$t4
srl $s0,$s0,16
and $s2,$s0,$t4
add $s0,$s1,$s2
End:
andi $s0,$s0,0x003f
在此处输入图像描述
在此处输入图像描述
MIPS解释
这是一个人口计数,又称爆炸式,又称锤子的重量。$s0
中的最终结果是输入中的1
位数。这是一个优化的实现,其结果与将每个位分开移到寄存器的底部并将其添加到总计相同。参见https://graphics.stanford.edu/~seander/bithacks.html#countbitssetnenaive
使用swar ,该实现从2位累加器到4位,8位和16位的构建作用,使用swar 进行多个狭窄的添加,这些狭窄添加不会彼此携带一项add
指令。
请注意,它如何掩盖每隔一点,然后是每一位,然后是每组4位。并使用轮班将另一对降低到add
排队。像C
(x & mask) + ((x>>1) & mask)
重复较大的偏移,另一个掩码最终为您提供所有位的总和(将它们都视为具有1个位置为1的位置(,即输入中的设置位数。
所以GNU C表示为__builtin_popcnt(x)
。
(除了编译器实际上将使用一个更有效的popcnt:单独使用每个字节的字节查找表,或者是以这种方式启动的bithack,但使用乘以 0x01010101
之类的数字来水平总和4个字节4结果的字节。因为乘法是一个移位指令。如何计算32位整数中的设置位数?(
,但这被打破了:它需要使用addu
来避免故障;如果您尝试popcnt 0x80000000
,则第一个add
将具有两个输入= 0x40000000
,从而产生签名的溢出和故障。
idk为什么有人在MIPS上使用add
指令。普通的二进制添加指令称为addu
。
添加 - 捕获 - 签名的OPRFLOF FLOWS指令是add
,即使您的数字已签名,也很少是您想要的。您最好忘记它存在并使用addu
/addui