c - 识别编译器产生的汇编程序中的某些组件

标签 c assembly compilation static-analysis

<分区>

这是我的问题:

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

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

那标记的组件是循环语句怎么办?甚至算术陈述?这个时候有什么好的解决办法吗?

谁能帮帮我?谢谢!

最佳答案

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

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

gcc 5.3 with -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

在更复杂的代码中:

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

如果代码是矢量化的,则查找包含 vector 指令的循环。 (例如,大量完全展开的标量 addsd 序言/结尾,然后是一个微小的 addpd 内循环。)


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

gcc auto-vectorizes this simple loop 进入标量代码直到对齐指针,然后是 vector 内循环,然后在最后一个完整 vector 之后进行清理。展开的标量序言/结尾使用交替颜色来标记正在检查循环条件的部分与执行循环体的部分。

关于c - 识别编译器产生的汇编程序中的某些组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37469990/

相关文章:

c - void** 是 ANSI-C 中可接受的类型吗?

c - 在不分配给变量的情况下调用内核内部的非空函数是否安全

c - 在 C 中不使用 "PACKED"编译器指令打包数据

gcc - 为什么底部测试循环更可取?

linux - 每个任务使用一个 cpu 核心

c++ - FLTK、wxWidgets、GTK - 轻便、易用且便携

assembly - 跳转到 64 位长模式时出现三重故障

assembly - 检查内存访问 x86-64 程序集

android - Ionic 2 RC0 和 Angular 2 最新构建 android 错误 (ngc : Error: Error encountered resolving symbol values statically)

C 预处理多遍