【问题标题】:Recognize certain components in the compiler produced assembly program [closed]识别编译器生成的汇编程序中的某些组件[关闭]
【发布时间】:2016-05-26 20:02:35
【问题描述】:

这是我的问题:

给定一个标记的C代码组件,如何在编译器生成的汇编程序中找到它对应的汇编指令?

如果标记的组件是一个函数,应该很容易,只要没有重叠的汇编程序,我们就可以在编译器生成的代码中进行线性搜索并识别函数。

那么标记的组件是一个循环语句呢?甚至是算术语句?目前有什么好的解决办法吗?

谁能帮帮我?谢谢!

【问题讨论】:

  • 没有理由假设这是可能的,即使使用编译器可以轻松内联的函数也是如此。在某些情况下,您可以在不进行优化的情况下进行编译,并要求编译器执行其他操作以使其更容易,但通常,尤其是优化后,并不假设一行代码之间存在一对一的关系和一团 asm。
  • 听起来像XY problem。 “找到相应的汇编指令”真的是你的最终目标吗?如果你陈述你实际想要达到的目标,也许有人可能有更好/更简单的方法来做到这一点。
  • 您是在问如何以编程方式执行此操作吗?只需使用调试信息。或者您是否要求检查 C 源代码中的某些内容如何编译成 asm 的技术? (即作为人类,如何通过臃肿的编译器输出)

标签: c assembly compilation static-analysis


【解决方案1】:

使用-fverbose-asm 编译。 gcc 在 asm 输出中的 cmets 比 clang 更冗长,变量名称可以帮助您找到您正在寻找的循环,但更多时候它们只是编号的内部临时变量。不过,ivtmp 可能代表迭代变量,而不是保存其他表达式结果的其他临时变量。

void foo(int*p) {
  for (int i=0 ; i<123456 ; i++ )
    p[i] = p[i] * 4 - 1;
}

gcc 5.3 与 -fverbose-asm -O3 -march=haswell -fno-tree-vectorize -fno-unroll-loops compiles it to 代码递增指针,当然使用 lea 进行移位和减法合二为一。

Clang -fverbose-asm 在循环顶部分支目标上添加注释,但不注释每一行。

foo:
    lea     rdx, [rdi+493824] # D.2351,
.L2:
    mov     eax, DWORD PTR [rdi]      # MEM[base: _17, offset: 0B], MEM[base: _17, offset: 0B]
    add     rdi, 4    # ivtmp.9,
    lea     eax, [-1+rax*4]   # tmp111,
    mov     DWORD PTR [rdi-4], eax    # MEM[base: _17, offset: 0B], tmp111
    cmp     rdx, rdi  # D.2351, ivtmp.9
    jne     .L2       #,
    ret

在更复杂的代码中:

要查找内部循环,请查找标签,紧随其后的是返回相同标签的分支。到处都会有标签,但是您正在寻找一个回到标签的分支,中间没有其他标签或分支。 (对于内部没有流量控制的简单循环)。

如果代码是向量化的,则查找包含向量指令的循环。 (例如,大量完全展开的标量 addsd prologue/epilogue,然后是一个很小的 ​​addpd 内循环。)


调试信息还将每条指令与负责它的源代码行相关联。有多种使用方法,包括像 Godbolt Compiler Explorer 那样对 asm 输出着色。

gcc auto-vectorizes this simple loop 转换为标量代码,直到对齐指针,然后是向量内部循环,然后在最后一个完整向量之后进行清理。展开的标量序言/尾声具有交替的颜色,以标记检查循环条件的部分与执行循环主体的部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多