我正在反编译一个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()获得绝对值的结果。这是有意义的,因为我总是在值被用作数组索引之前遇到这个片段,它不能为负。
现在,我不太确定了,因为从那以后,我看到它被用在允许和考虑负数的情况下。
有谁知道这个密码是干什么用的吗?
1条答案
按热度按时间vjhs03f71#
如果
li
不在较早分支的分支延迟槽中,它就没用。你是对的,它的结果被覆盖,因此没有效果。在
li
之后,代码看起来像是在做2
或256
的有符号除法,像Cx /= 256
那样向0舍入,而不是像x >>= 8
那样向-Inf
舍入。我想知道它是为了调试还是什么,在反汇编或调试器中找到块?既然你说游戏带有调试符号,那么它可能是故意的。
在这两种情况下,加载到
v1
中的值都是除数,它正在执行v1 = s1 / v1
,但实际上并没有使用来自v1的值。或者是一些手写的asm,或者是一个笨拙的编译器,它的窥视孔优化错误,并留在一个无用的指令?