如何编写 C 代码,以便生成的 ASM 使用加载较小数据块的指令?

问题描述 投票:0回答:1

我正在反编译作为调试版本提供的 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

assembly mips reverse-engineering
1个回答
0
投票

原始的 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];
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.