1

我正在学习汇编代码,给定这段代码,我需要找出这段代码是关于什么的。但是我正在尝试使用 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 解释

4

1 回答 1

1

这是一个人口计数,又名 popcount,又名 Hamming Weight。最终结果$s01输入中的位数。这是一个优化的实现,其结果与将每个位分别移动到寄存器的底部并将其添加到总数中相同。见https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive

此实现通过使用SWAR将2 位累加器构建为 4 位、8 位和 16 位来执行多个窄加法,这些加法器不会通过一条add指令相互进位。

注意它是如何屏蔽所有其他位的,然后是每对位,然后是每组 4 位。并使用轮班将另一对拉下来排队等待add。像C
(x & mask) + ((x>>1) & mask)

使用更大的移位和不同的掩码重复此操作最终会为您提供所有位的总和(将它们全部视为具有 1 的位置值),即输入中设置的位数。

所以这个的 GNU C 表示是__builtin_popcnt(x).

(除了编译器实际上将使用更有效的 popcnt:分别为每个字节使用字节查找表,或者以这种方式开始的 bithack,但使用乘以一个数字,例如0x01010101将 4 个字节水平相加到结果的高字节中.因为乘法是移位加法指令。 如何计算32位整数中设置的位数?


但这被打破了:它需要使用addu以避免故障;如果您尝试 popcnt 0x80000000,第一个add将有两个输入 = 0x40000000,从而产生有符号溢出和故障。

IDK 为什么有人使用addMIPS 上的指令。调用正常的二进制加法指令addu

add-with-trapping-on-signed-overflow 指令是add,即使您的数字已签名,这也很少是您想要的。您不妨忘记它的存在并使用addu/addui

于 2019-07-08T05:53:30.897 回答