我正在查看C应用程序的非常可疑的反汇编MIPS代码
80019B90 jal loc_80032EB4
loc_80032EB4位于另一个函数体的中间,我特意检查过在运行时没有其他代码加载到此地址并以这种方式调用该函数(在开头传递一些代码)可以很有用。但是怎么可能用C做呢?它不是一个goto,因为你可以转到另一个函数,正常的函数调用将始终" jal"到了开头。这可能是一些手动化吗?
更新
两个函数的简化布局,被调用者:
sub_80032E88 (lz77_decode)
... save registers ...
80032E90 addiu $sp, -8
... allocate memory for decompressed data ...
80032EB0 move DECOMPRESSED_DATA_POINTER_A1, $v0
loc_80032EB4:
80032EB4 lw $t7, 0(PACKED_DATA_POINTER_A0)
... actual data decompression ...
80032F4C jr $ra
呼叫者:
80019ACC addiu $sp, -0x30
... some not related code ...
80019B88 lw $a1, off_80018084 // A predefined buffer is used instead of allocating it for decompressed data
80019B90 jal loc_80032EB4
80019B94 move $a0, $s0
... some other code and function epilogue ...
更新2: 我已经检查过这是否是setjmp / longjmp使用的情况,但在我的测试中,我总是可以看到在反汇编代码中调用setjmp和longjmp函数,而不是直接跳转。
更新3: 我尝试使用GCC特定的能力获取标签指针并将此指针转换为函数,结果接近我想要的但是反汇编代码仍然不同,而不是使用带有exaxct地址的jal它计算运行时,也许我我只是无法强制编译器将此值视为常量,因为范围问题。
答案 0 :(得分:1)
由于它是来自游戏系统的数据解压缩功能,因此该功能很可能是具有多个入口点的手动优化组件。多个入口点并不常用,因此很难找到公开的示例,但here是来自gcc邮件列表的旧线程,暗示了此技术的可能用途。
要点是,如果你有两个函数,其中一个函数 F1 的代码是另一个函数的子集, F2 的代码,则代码为 F2 可以落入 F1 的代码中。在您的情况下, F2 为解压缩数据分配内存, F1 假定已完成内存分配。我很确定GCC 2.9x无法生成这样的代码。
不可能将此构造从汇编程序直接转换为标准C,因为您不能在C中goto
另一个函数,但这在汇编代码中是完全合法的。 gcc邮件列表主题建议在C中表达相同的想法。
如果查看解压缩的解组代码,它可能会有与编译器生成的代码不同的样式。甚至可能会使用编译器无法从C生成的find first set bit等操作码。