“原因可能是什么?”;日航";到MIPS中另一个函数的中间

“原因可能是什么?”;日航";到MIPS中另一个函数的中间,mips,disassembly,function-calls,Mips,Disassembly,Function Calls,我正在看一个非常可疑的C应用程序的反汇编MIPS代码 80019B90 jal loc_80032EB4 Loopy8032 EB4位于另一个函数的主体中,我特别检查了在运行时没有其他代码加载在这个地址上,这样调用这个函数(在开始时传递一些代码)是有用的。但是如何在C中实现呢?这不是一个转到,因为你不能转到另一个函数,正常的函数调用总是从“jal”开始。这是不是可以用手做的 更新: 两个函数的简化布局,被调用方: sub_80032E88 (lz77_

我正在看一个非常可疑的C应用程序的反汇编MIPS代码

80019B90                 jal     loc_80032EB4

Loopy8032 EB4位于另一个函数的主体中,我特别检查了在运行时没有其他代码加载在这个地址上,这样调用这个函数(在开始时传递一些代码)是有用的。但是如何在C中实现呢?这不是一个转到,因为你不能转到另一个函数,正常的函数调用总是从“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特定的功能获取标签指针并将此指针转换为函数,结果接近我想要的结果,但反汇编代码仍然不同,因为没有使用jal和exaxct address来计算它的运行时,可能我只是无法强制编译器将此值视为常量,由于范围问题。

由于它是游戏系统中的数据解压功能,因此该功能很可能是具有多个入口点的手动优化组装。多个入口点并不常用,因此很难找到一个公开的示例,但这是gcc邮件列表中的一个旧线程,表明了此技术的可能用途

要点是,如果有两个函数,其中一个函数F1的代码是另一个函数F2的代码的子集,则F2的代码可以归入F1的代码。在您的例子中,F2为解压缩的数据分配内存,F1假设内存分配已经完成。我很确定GCC2.9x不能生成这样的代码

不可能直接将此结构从汇编程序转换为标准C,因为您不能
goto
C中的另一个函数,但这在汇编程序代码中是完全合法的。gcc邮件列表线程建议使用两种变通方法在C中表达相同的想法


如果您查看解压的分解代码,它可能与编译器生成的代码具有不同的样式。甚至可能会使用一些操作码,比如编译器无法从C生成操作码。

没有足够的上下文来回答这个问题。那是有效代码中的日本航空公司吗?跳转到什么?我已经用函数布局更新了问题。日本航空公司的代码是有效的,用这种方式使用它是有意义的。这确实是一个错误。那是哪个编译器?我认为即使编译器在两个不同的调用站点内联了一个裸函数,在gcc中也无法做到这一点。这是一个playstation 1二进制文件,我相信它是用一个非常旧的(大约1998年)编译的索尼对gcc进行了一些修改,以适应他们的工具链。确切的版本是GNU C 2.95.2。不幸的是,我无法发现解压代码和调用函数风格的任何差异。要尝试多个入口点,请您将我链接到一个示例,我找不到一个…尽管我非常努力地寻找构建标志和各种代码片段的神奇组合,但我找不到任何方法在没有asm的情况下强制编译器这样做,所以您的想法似乎是正确的。尽管我会更新这个问题,如果我发现有一个C代码能够做到这一点。你可以用C来表达这个概念,方法是在较大的函数结束时对第二个函数进行尾调用。一个聪明的编译器会把一个放在另一个之前,这样它就可以通过而不是真正的跳跃。(真正的编译器并没有那么聪明,但如果你要翻译回C,你只需要匹配的逻辑,而不管你是否真的要编译回asm)