
编辑:我应该补充一点,我不是在寻找一个反汇编程序. C源代码和汇编代码之间存在巨大差距.在这个鸿沟内部是复杂的事情,比如模板元编程和对运算符方法的各种隐式调用(赋值!强制转换!构造函数!…)以及具有非常复杂的分辨率规则的重载函数等等.我正在寻找工具,以帮助我理解C编译器如何解释我的代码.现在,我唯一能做的就是尝试一些实验,然后逐步了解编译器正在做什么.我想看看有关正在发生的事情的更多细节.例如,在调试模板元编程问题时,这将有很大帮助.
解决方法 目前,我认为你最好的选择是Clang(你可以在 Try Out LLVM页面上尝试一些简单的代码).使用Clang / LLVM编译C,C或Obj-C时,您可以要求编译器发出中间表示(LLVM IR),而不是完全采用汇编/二进制形式.
LLVM IR是编译器内部使用的完整指定语言:
> CLang将C代码降低到LLVM IR
> LLVM优化IR
> LLVM后端(例如x86)从IR生成程序集
IR是机器特定代码之前的最后一步,因此您不必学习特定的汇编指令,而且您仍然可以非常低级地表示真正发生的事情.
您可以在优化之前和之后获得IR,后者更能代表实际代码,但远离您最初编写的内容.
C程序示例:
#include <stdio.h>#include <stdlib.h>static int factorial(int X) { if (X == 0) return 1; return X*factorial(X-1);}int main(int argc,char **argv) { printf("%d\n",factorial(atoi(argv[1])));} 相应的IR:
; ModuleID = '/tmp/webcompile/_10956_0.bc'target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"target triple = "x86_64-unkNown-linux-gnu"@.str = private unnamed_addr constant [4 x i8] c"%dA"define i32 @main(i32 %argc,i8** nocapture %argv) nounwind {; <label>:0 %1 = getelementptr inbounds i8** %argv,i64 1 %2 = load i8** %1,align 8,!tbaa !0 %3 = tail call i64 @strtol(i8* nocapture %2,i8** null,i32 10) nounwind %4 = trunc i64 %3 to i32 %5 = icmp eq i32 %4,0 br i1 %5,label %factorial.exit,label %tailrecurse.itailrecurse.i: ; preds = %tailrecurse.i,%0 %indvar.i = phi i32 [ %indvar.next.i,%tailrecurse.i ],[ 0,%0 ] %accumulator.tr1.i = phi i32 [ %6,[ 1,%0 ] %X.tr2.i = sub i32 %4,%indvar.i %6 = mul nsw i32 %X.tr2.i,%accumulator.tr1.i %indvar.next.i = add i32 %indvar.i,1 %exitcond = icmp eq i32 %indvar.next.i,%4 br i1 %exitcond,label %tailrecurse.ifactorial.exit: ; preds = %tailrecurse.i,%0 %accumulator.tr.lCSSa.i = phi i32 [ 1,%0 ],[ %6,%tailrecurse.i ] %7 = tail call i32 (i8*,...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str,i64 0,i64 0),i32 %accumulator.tr.lCSSa.i) nounwind ret i32 0}declare i32 @printf(i8* nocapture,...) nounwinddeclare i64 @strtol(i8*,i8** nocapture,i32) nounwind!0 = Metadata !{Metadata !"any pointer",Metadata !1}!1 = Metadata !{Metadata !"omnipotent char",Metadata !2}!2 = Metadata !{Metadata !"Simple C/C++ TBAA",null} 我个人发现它相对可读(一旦你超越了语言的原始发现,它试图保留变量名,有些,函数名仍然存在).
总结以上是内存溢出为你收集整理的怎么看降低c全部内容,希望文章能够帮你解决怎么看降低c所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)