我正在反编译作为调试版本提供的 PS2 游戏。为了验证我的 C 代码与原始代码是否匹配,我使用最初使用的编译器 (Metrowerks CodeWarrior) 对其进行编译,反汇编 ELF 文件,然后比较反汇编结果。
找到所述编译器的正确版本后,我几乎可以完全匹配反汇编。我仍然困惑的是本地数组的初始化。
这是原始的 ASM:
lui a3,hi(@113+259)
addiu a3,a3,lo(@113+-12800)
addiu a2,sp,160
li a1,4
lw a0,0(a3)
lw v1,4(a3)
addiu a3,a3,8
addiu a1,a1,-1
sw a0,0(a2)
sw v1,4(a2)
addiu a2,a2,8
bgtz a1,*-28
这应该与函数顶部的以下 C 代码匹配:
int_union* patsettbl[8] =
{
0,
&scra_h_posit,
&scrb_h_posit,
&scrc_h_posit,
0,
&scra_v_posit,
&scrb_v_posit,
&scrc_v_posit
};
但是当我编译它时,我得到以下 ASM:
lui v1,hi(@112+259)
addiu v1,v1,lo(@112+-13568)
addiu a1,sp,160
lq a0,0(v1)
lq v1,16(v1)
sq a0,0(a1)
sq v1,16(a1)
如您所见,它使用加载较大数据块的指令来填充数组,而不是在循环内加载较小数据块。
有人告诉我这种行为取决于编译器。但我知道他们使用了 CodeWarrior,因为调试信息中有一个字符串:“MW MIPS C Compiler (2.4.1.01).PlayStation2”。
有谁知道我可能做错了什么?
如果有帮助,这里有一个划痕:https://decomp.me/scratch/8RF78
原始的 C 代码可能使用循环来显式复制常量。此外,您的类型和初始值设定项非常可疑,因为元素看起来更像成对结构。我希望它们是 h/v 对。我的猜测更多的是:
struct pair
{
int_union* h;
int_union* v;
};
static const struct pair init[4] = {
{ 0, 0 },
{ &srca_h_posit, &srca_v_posit },
{ &srcb_h_posit, &srcb_v_posit },
{ &srcc_h_posit, &srcc_v_posit },
};
void foo()
{
struct pair patsettbl[4];
for(int i = 4; i > 0; i--)
{
patsettbl[i] = init[i];
}
}