gpt4 book ai didi

assembly - 汇编语言的自动代码去重?

转载 作者:行者123 更新时间:2023-12-02 19:13:32 24 4
gpt4 key购买 nike

我经历过一些Assembly Programming Videos更好地了解如何手动优化使用 gcc/g++ -S ... 编译后留下的 *.s 文件 其中涵盖的主题之一是 Refactoring Redundant Code演示了如何将冗余代码移动到其自己的以 ret 结尾的标记 block 中。并将其替换为 call .

视频中给出的示例是 2 个 block ,其中包含:

mov eax,power
mul ebx
mov power,eax
inc count

它替换为调用CalculateNextPower并且CalculateNextPower看起来像:

CalculateNextPower:
mov eax,power
mul ebx
mov power,eax
inc count
ret

出于好奇,为了减少编译大小,我使用 -S 和各种优化(包括 -Os、-O2、-O3、-pipe、-combine 和 -fwhole-program)编译了一些 C 和 C++ 项目,并分析了结果*.s 文件使用 duplo 的轻微修补(对于 .s 文件)版本来实现冗余。只有 -fwhole-program (现已弃用 IIRC) 对消除文件间的重复代码有显着效果 (我假设它的替代品 -flto 在链接时的行为类似 - 大致相当于使用 -ffunction-sections -fdata-sections 进行编译并使用 --gc-sections 进行链接),但仍然会丢失相当大的代码块。

当仅对具有至少 5 个连续重复指令的连续汇编 block 进行重复数据删除时,使用 duplo 输出进行手动优化可在随机 C 项目中减少约 10% 的大小,在随机 C++ 项目中减少近 30% 的大小。

我是否缺少一个编译器选项(甚至是一个独立工具),可以在编译大小时自动消除冗余汇编(包括其他编译器:clang、icc等..)或者是此功能不存在(出于某种原因?)?

如果不存在,可以修改 duplo忽略以“.”开头的行或者 ';' (和其他?) 并用对具有重复代码的函数的调用来替换重复的代码块,但我愿意接受其他可以直接与编译器的内部表示一起使用的建议(最好是 clang 或 gcc)。

编辑:我修补了 duplo 以识别重复程序集的 block here ,但目前仍然需要手动重构。只要使用相同的编译器来生成代码,就有可能(但可能很慢)识别最大的重复代码块,将它们放入自己的“函数” block 中,并用对该 block 的 CALL 替换代码.

最佳答案

你想要的是 clone detector tool

这些存在于各种实现中,具体取决于正在处理的文档元素的粒度以及可用结构的数量。

那些匹配原始行的(对你不起作用,你想通过不同的常量[数据和索引偏移量]和/或命名位置或其他命名子例程来参数化你的子例程)。基于 token 的检测器可能会起作用,因为它们将识别变化的单点位置(例如,常量或标识符)。但你真正想要的是一个结构匹配器,它可以挑选出变体寻址模式,甚至是 block 中间代码中的变体(请参阅我碰巧构建的基于 AST 的克隆检测器)。

要使用结构进行检测,您必须拥有结构。幸运的是,即使是汇编语言代码也具有语法形式的结构,以及由子例程入口和导出分隔的代码块(后者在汇编中检测起来有点问题,因为每种代码可能不止一个)。

当您检测到使用结构时,您至少有可能使用该结构来修改代码。但是,如果您将程序源表示为一棵树,那么您就有了用于检测克隆的结构(子树和子树序列),并且可以通过修改匹配点处的树来抽象克隆匹配。 (我的 COBOL 克隆检测器的早期版本将克隆抽象为 COPY 库。我们停止这样做主要是因为您不想以这种方式抽象每个克隆)。

关于assembly - 汇编语言的自动代码去重?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19663795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com