繁体   English   中英

如何从汇编程序指令转到C代码

[英]How to go From Assembler instruction to C code

我有一个任务,除其他外,我需要在.asm文件中查找某个指令和“反向工程”(找出)C代码的哪一部分导致它在汇编程序级别执行。 (文字下方的例子)

什么是最快(最简单)的方法。 或者更好地说,.asm文件中的其他命令/指令/标签应该/我可以注意什么,这将指导我使用正确的C代码?

我几乎没有使用汇编代码的经验,很难弄清楚C代码的确切行会导致特定指令发生。

如果这有任何区别,那么这个架构就是TriCore。

示例:通过跟踪使用变量的位置,我设法找出C代码在asm文件中导致插入的内容

 .L23:
    movh.a  a15,#@his(InsertStruct)
    ld.bu   d15,[a15]@los(InsertStruct)
    or  d15,#1
    st.b    [a15]@los(InsertStruct),d15
.L51:
    ld.bu   d15,[a15]@los(InsertStruct)
    insert  d15,d15,#0,#0,#1
    st.b    [a15]@los(InsertStruct),d15
.L17:
    mov d15,#-1

这导致我得到以下C代码:

InsertStruct.SomeMember = 0x1u;

InsertStruct.SomeMember = 0x0u;

我应该修补现有的指令集测试,它不测试所有使用的指令。 所以我需要查看一级代码的asm文件,找出C代码导致指令发生的原因,以便我可以在我的补丁中使用它。

你的目标是疯狂的 ,你的问题的前半部分是向后/只与你真正的问题松散相关。

可能有一种方法可以说服您的编译器使用您想要的每个特定指令,但它将特定于您的编译器版本,选项和所有周围的代码,包括头文件中的潜在常量。

如果你想测试ISA中的所有指令,希望你可以说服C编译器以某种方式生成它们是完全错误的方法。 你希望你的测试将来继续测试同样的东西,所以你应该这样做。 如果您需要特定的asm,请写入asm

这是几周前针对ARM提出的问题: 如何强制IAR使用所需的Cortex-M0 +指令(优化将被​​禁用此功能。),除非您说您要构建并启用优化(可能使得更容易获得更广泛的指令生成:有些可能仅用作简单普通代码的窥视孔优化)。


另外,从asm开始并将其反转为等效的C并不能保证编译器在编译时会选择该指令,因此问题标题只与您的实际问题松散相关。


如果您仍然希望手持编译器来生成特定的asm,要创建可能只使用非常特定的编译器/版本/选项执行所需的脆弱源代码,第一步是考虑“ 此指令何时为做某事的优化方式的一部分?

通常,这种思路对于优化更有用,可以通过调整源代码来更有效地进行编译。 首先,您要考虑一个有效的asm实现您正在编写的函数。 然后以相同的方式编写C或C ++源代码,即使用您希望编译器将使用的相同临时值。 例如,请参阅在某个位置或更低位置计算设置位的有效方法是什么? 在那里我能够使用更有效的指令序列来手持gcc,就像clang为我的第一次尝试做的那样。

有时这可以很好地运作; 为了您的目的,当指令集只有一个非常好的方法来做某事时,它很简单。 例如, ld.bu看起来像一个字节加载,零扩展( u表示无符号)成为一个完整的寄存器。 unsigned foo(unsigned char*p) {return *p;}应编译为,并且你可以使用noinline属性来阻止它优化。

但是, insert ,如果这是插入零位进位域,可以很容易地一直在and~1 (0xFE的),假设的TriCore拥有和直接。 如果insert具有非立即形式,那么对于single-bit bitfield = rand() (或者在使用常量传播进行优化之后仍然不是编译时常量的任何值single-bit bitfield = rand() ,这可能是最有效的选择。

对于TriCores的压缩算术(SIMD)指令,您将需要编译器自动向量化或使用内在函数。

ISA中可能存在一些编译器永远不会发出的指令。 虽然我认为你只是试图测试编译器在代码的其他部分发出的指令? 你说“所有使用的指令”,而不是“所有指令”,所以至少保证任务是可能的。


带有arg的非内联函数是强制运行时变量的代码生成的绝佳方法。 看看编译器生成的asm的那些使用者经常编写小函数,这些函数接受args并返回一个值(或存储到全局或volatile )以强制编译为某些东西生成代码而不丢弃结果,并且没有不断传播的转向整个功能return 42; ,即mov -immediate / ret 请参阅如何从GCC /铿锵声组件输出中删除“噪音”? 更多关于这一点,以及Matt Godbolt的CppCon2017谈话:“ 我的编译器最近为我做了什么? 解开编译器的盖子 “对于阅读编译器生成的asm的一些很好的初学者介绍,以及现代优化编译器为小函数做什么样的东西。

分配给volatile然后读取该变量将是另一种阻止常量传播的方法,即使对于需要在没有外部输入的情况下运行的测试,如果这比使用noinline函数更容易。 (编译器在C源中读取的每个单独时间都从volatile重新加载,即他们必须假设它可以异步修改。)

int main(void) {
    volatile int vtmp = 123;
    int my_parameter = vtmp;

    ... then use my_parameter, not vtmp, so CSE and other optimizations can still work
 }

[...]它已经过优化

您显示的编译器输出肯定不会看起来优化。 它看起来像加载/设置一个位/存储,然后加载/清除一个位/存储,它应该已经优化到只加载/清除位/存储。 除非那些asm块不是真正连续的,并且你正在显示粘贴在一起的两个不同块的代码。

另外, InsertStruct.SomeMember = 0x0u; 是一个不完整的描述:它显然取决于结构定义; 我假设你使用了一个int SomeMember :1; 单比特位域成员? 根据我发现的这个TriCore ISA参考手册insert在指定的插入位置将一系列位从一个寄存器复制到另一个寄存器,并以寄存器和即时源形式存在。

替换整个字节可能只是一个存储而不是读/修改/写。 所以这里的关键是结构定义,而不仅仅是编译到指令的语句。

该架构是TriCore(如果这有任何区别)。

当然。 汇编代码始终是特定于体系结构的。

... C代码的哪一部分导致它在汇编程序级别执行。

使用高度优化的编译器时,您几乎没有机会:

例如,TriCore的Tasking编译器有时甚至会为两个不同的C文件中的两个不同的C代码行生成一个汇编代码片段(在内存中只存储一次!)!

但是,示例中的代码未进行优化(除非您命名为InsertStruct的结构是volatile )。

在这种情况下,您可以在打开调试信息的情况下编译代码并提取调试信息:从ELF格式文件中,您可以使用addr2line (GNU编译器套件中的免费软件)等工具来检查哪一行C代码对应于以下指令:某个地址。

(注意: addr2line工具是独立于体系结构的,只要两个体系结构具有相同的宽度(32位),相同的字节顺序并且都使用ELF文件格式;您可以使用addr2line for ARM从TriCore文件获取信息。)

如果您真的必须了解汇编代码的片段,我自己通常会执行以下操作:

我启动一个文本编辑器并粘贴汇编代码:

movh.a  a15,#@his(InsertStruct)
ld.bu   d15,[a15]@los(InsertStruct)
or      d15,#1
st.b    [a15]@los(InsertStruct),d15
...

然后我用伪代码替换每条指令:

a15 =  ((((unsigned)&InsertStruct)>>16)<<16;
d15 =  *(unsigned char *)(a15 + (((unsigned)&InsertStruct)&0xFFFF));
d15 |= 1;
*(unsigned char *)(a15 + (((unsigned)&InsertStruct)&0xFFFF)) = d15;
...

在下一步中,我尝试简化此代码:

a15 =  ((unsigned)&InsertStruct) & 0xFFFF0000;

然后:

d15 = *(unsigned char *)((((unsigned)&InsertStruct) & 0xFFFF0000) + (((unsigned)&InsertStruct)&0xFFFF));
...

然后:

d15 = *(unsigned char *)((unsigned)&InsertStruct);
...

然后:

d15 = *(unsigned char *)&InsertStruct;
...

最后我尝试替换跳转指令:

d15 = 0;
if(d14 == d13) goto L123;
d15 = 1;
L123:

......变成:

d15 = 0;
if(d14 != d13) d15 = 1;

......最后(也许):

d15 = (d14 != d13);

最后,您在文本编辑器中有C代码。

不幸的是,这需要长时间 - 但我不知道任何更快的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM