assembly 在将右移值放入寄存器之前,先将值加载到寄存器的目的是什么?

gxwragnw  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(96)

我正在反编译一个PS2游戏,它最初是用C编写的。为此,我正在阅读MIPS汇编程序并编写相应的C语句。
有一个反复出现的模式我一直没弄明白。考虑以下组件:

li     v1,2
sra    v1,s1,1
bgez   s1,*+16
nop    
addiu  v1,s1,1
sra    v1,v1,1
daddu  s1,v1,$0

字符串
立即值2被加载到寄存器v1中,并且立即被寄存器s1的一位右移值重写。接下来,它检查s1是否为正数,如果不是,则将s1加1加载到v1中,并像前面一样将其向右移动一位。在这两种情况下,结果都被复制回s1。
当向右移动更多位时,也出现了相同的模式。在这里,它向右移动8位,立即值被更改为匹配:

li     v1,256
sra    v1,s1,8
bgez   s1,*+16
nop    
addiu  v1,s1,255
sra    v1,v1,8
daddu  s1,v1,$0


经过一番思考,这让我想起了2的补码,所以我认为这是使用C标准库函数abs()获得绝对值的结果。这是有意义的,因为我总是在值被用作数组索引之前遇到这个片段,它不能为负。
现在,我不太确定了,因为从那以后,我看到它被用在允许和考虑负数的情况下。
有谁知道这个密码是干什么用的吗?

vjhs03f7

vjhs03f71#

如果li不在较早分支的分支延迟槽中,它就没用。你是对的,它的结果被覆盖,因此没有效果。
li之后,代码看起来像是在做2256的有符号除法,像C x /= 256那样向0舍入,而不是像x >>= 8那样向-Inf舍入。
我想知道它是为了调试还是什么,在反汇编或调试器中找到块?既然你说游戏带有调试符号,那么它可能是故意的。
在这两种情况下,加载到v1中的值都是除数,它正在执行v1 = s1 / v1,但实际上并没有使用来自v1的值。
或者是一些手写的asm,或者是一个笨拙的编译器,它的窥视孔优化错误,并留在一个无用的指令?

相关问题