我想检查boost::variant在我的代码中应用的程序集输出,以便查看哪些中间调用被优化掉了.
当我编译以下示例(使用GCC 5.3 g++ -O3 -std=c++14 -S)时,似乎编译器优化了所有内容并直接返回100:
(...)
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
(...)
Run Code Online (Sandbox Code Playgroud)
#include <boost/variant.hpp>
struct Foo
{
int get() { return 100; }
};
struct Bar
{
int get() { return 999; }
};
using Variant = boost::variant<Foo, Bar>;
int run(Variant v)
{
return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
Foo f;
return run(f);
}
Run Code Online (Sandbox Code Playgroud)
但是,完整的程序集输出包含的内容远远超过上面的摘录,对我而言,它看起来永远不会被调用.有没有办法告诉GCC/clang删除所有"噪音"并输出程序运行时实际调用的内容?
完整装配输出:
.file "main1.cpp"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1: …Run Code Online (Sandbox Code Playgroud) 所以我发现C(++)程序实际上并没有编译成简单的"二进制"(我可能在这里遇到了一些问题,在这种情况下我很抱歉:D)但是对于一系列事物(符号表) ,os相关的东西,...)但......
汇编程序"编译"到纯二进制文件?这意味着除了预定义的字符串等资源之外没有额外的东
如果C编译成除了普通二进制文件以外的其他内容,那么小型汇编程序引导程序如何只是将指令从HDD复制到内存并执行它们?我的意思是,如果操作系统内核(可能用C语言编写)编译成不同于普通二进制文件的东西 - 引导加载程序如何处理它?
编辑:我知道汇编程序没有"编译",因为它只有你的机器的指令集 - 我没有找到汇编程序"汇编"的好词.如果你有一个,请留在这里作为评论,我会改变它.
我主要对流行的和广泛使用的编译器感兴趣,比如gcc.但如果不同的编译器对事情做了不同的事情,我也想知道.
以gcc为例,它是否将用C编写的简短程序直接编译为机器代码,或者首先将其转换为人类可读的汇编,然后才使用(内置?)汇编程序将汇编程序转换为二进制,机器代码 - CPU的一系列指令?
使用汇编代码创建二进制可执行文件是一项非常昂贵的操作吗?或者这是一个相对简单快速的事情?
(假设我们只处理x86系列处理器,所有程序都是为Linux编写的.)
我对此事的任何帮助和想法都非常感激.谢谢!
C++编译器是否通过汇编语言代码生成机器代码(即,c ++编译器首先将C++代码转换为汇编语言代码,然后使用汇编语言编译器将其转换为机器代码),或者汇编语言输出生成只是一个参考选项或调试目的?
如果编译器将高级语言转换为机器代码,为什么我们甚至需要汇编程序呢?是否有任何汇编级语言,我们不能使用编译器?
我有困惑.我是C++开发人员,并多次听说我的源代码将首先转换为程序集,然后程序集将转换为机器代码.但是在汇编语言的一个视频教程中,教师清楚地说,C/C++代码直接转换为机器代码.(当然会有链接和加载).
我见过像这样的链接, C++代码是否编译成汇编代码?
我仍然无法澄清我的怀疑.
如果以防万一,C++没有首先转换为汇编,那么反汇编器如何从二进制生成汇编代码.
为了缩小我的问题范围,让我描述一下我的假设和我所做的实验......
我的假设:用汇编语言编写的代码将比 C/C++ 对应的代码运行得快得多,并且可执行文件的大小也比 C/C++ 代码生成的代码小得多。
实验:我将以下程序写入bin2dec.c
#include <stdio.h>
int main()
{
long int binary, decimal, reminder, exp;
int i, j;
for(i=0; i<10000; i++)
{
for(j=0; j<1000; j++)
{
binary = 11000101;
exp = 1;
decimal = 0;
while(binary != 0)
{
reminder = binary % 10;
binary = binary / 10;
decimal = decimal + reminder * exp;
exp *= 2;
}
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后为其生成ASM代码gcc -S bin2dec.c -o bin2dec.s
之后我编译了两个文件,如下所示
gcc bin2dec.c -o bin2dec_c …Run Code Online (Sandbox Code Playgroud) 我开始学习C++,我了解到编译器通过编译将源代码从程序转换为机器代码。
但是,我了解到 C++ 编译器实际上将源代码转换为程序集,作为将程序集代码转换为机器代码之前的中间步骤。这一步的目的是什么?
当我运行我的代码(任何代码)时,在调试模式下我可以选择“反汇编”。
我知道“反汇编”是从机器代码(存储在目标文件中的“1”和“0”)创建汇编代码。
所以,我可以假设当我在 Visual Studio 中编译我的代码时,在 C/C++ 代码到机器代码/目标文件之间没有“汇编/汇编”阶段,如果我想查看汇编代码,我需要要求 Visual Studio 将其从目标文件反汇编为程序集。
所以我的问题是:
我说的对,除了反汇编就没有办法看到asm了吗?
(如果 1 为否):为什么 Visual Studio 的调试器显示“反汇编”选项,而不是“汇编”?
Clang/GCC 是否有汇编阶段,或者 C/C++ 代码是否直接编译为目标代码?
编者按:对于 GCC 与大多数其他主流 C/C++ 编译器(如 clang/LLVM 和 MSVC),3 的答案实际上有所不同。由于这是与 MSVC 的工作方式不同的问题,因此该部分是这些其他 SO Q&A 的副本: