从代码到可执行程序的四个阶段:
预处理-->编译-->汇编-->链接
一步完成从代码到可执行程序:
对c程序来说使用
gcc name.c -o name.exe
执行命令后会生成可执行文件 name.exe。
对c++程序来使用
g++ name.cpp -o name.exe
执行命令后生成可执行文件name.exe。
gcc和g++的区别:
对C程序来说,gcc使用c代码的方式编译 ,而g++则使用C++代码的方式编译。注意:使用C++的方式编译C代码可能会出错。
对C++程序来说,两者没有差别。
四个阶段完成从代码到可执行程序:
源文件b.cpp代码如下:
#include<iostream>
using namespace std;
/*
这是一个注释!
*/
int main()
{
cout<<"c++ program!"<<endl;
system("pause");
return 0;
}
1、预处理
g++ -E(大写) name.cpp
-E 选项用来对原代码做预处理操作。使用 g++ -E b.cpp命令后,只会将预处理指操作的结果输出到屏幕,若想保存操作结果则要搭配-o使用。
预处理主要处理源文件和头文件中以#开头的命令(#
运行g++ -E b.cpp -o b.i会生成一个b.i文件
打开b.i文件后可以看到一些信息,发现其中注释已经被删掉了,头文件被替换为好多行代码。
# 1 "b.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "b.cpp"
# 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 1 3
# 36 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 3
# 37 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/iostream" 3
# 1 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 1 3
# 236 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 3
# 236 "C:/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/x86_64-w64-mingw32/bits/c++config.h" 3
namespace std
{
typedef long long unsigned int size_t;
typedef long long int ptrdiff_t;
typedef decltype(nullptr) nullptr_t;
.....
.....
.....
.....
.....
extern istream cin;
extern ostream cout;
extern ostream cerr;
extern ostream clog;
extern wistream wcin;
extern wostream wcout;
extern wostream wcerr;
extern wostream wclog;
static ios_base::Init __ioinit;
}
# 2 "b.cpp" 2
# 3 "b.cpp"
using namespace std;
int main()
{
cout<<"c++ program!"<<endl;
system("pause");
return 0;
}
2、编译
g++ -S(大写) name.cpp / name.i
使用该g++ -S b.cpp 后会自动生成b.s汇编代码文件,将c++代码翻译为汇编代码。
g++ -S指令并非必须经过预处理后的.i文件,-S选项的功能是令GCC编译器将指定文件预处理至编译阶段结束。
也就是说g++ -S可以处理.i文件,也可以处理原代码文件。
.file "b.cpp"
.text
.section .rdata,"dr"
_ZStL19piecewise_construct:
.space 1
.lcomm _ZStL8__ioinit,1,1
.def __main; .scl 2; .type 32; .endef
.LC0:
.ascii "c++ program!\0"
.LC1:
.ascii "pause\0"
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
.LFB1573:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
call __main
leaq .LC0(%rip), %rdx
movq .refptr._ZSt4cout(%rip), %rcx
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movq .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(%rip), %rdx
movq %rax, %rcx
call _ZNSolsEPFRSoS_E
leaq .LC1(%rip), %rcx
call system
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.def __tcf_0; .scl 3; .type 32; .endef
.seh_proc __tcf_0
__tcf_0:
.LFB2063:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
leaq _ZStL8__ioinit(%rip), %rcx
call _ZNSt8ios_base4InitD1Ev
nop
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.def _Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
.seh_proc _Z41__static_initialization_and_destruction_0ii
_Z41__static_initialization_and_destruction_0ii:
.LFB2062:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
movl %ecx, 16(%rbp)
movl %edx, 24(%rbp)
cmpl $1, 16(%rbp)
jne .L6
cmpl $65535, 24(%rbp)
jne .L6
leaq _ZStL8__ioinit(%rip), %rcx
call _ZNSt8ios_base4InitC1Ev
leaq __tcf_0(%rip), %rcx
call atexit
.L6:
nop
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.def _GLOBAL__sub_I_main; .scl 3; .type 32; .endef
.seh_proc _GLOBAL__sub_I_main
_GLOBAL__sub_I_main:
.LFB2064:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $32, %rsp
.seh_stackalloc 32
.seh_endprologue
movl $65535, %edx
movl $1, %ecx
call _Z41__static_initialization_and_destruction_0ii
nop
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.section .ctors,"w"
.align 8
.quad _GLOBAL__sub_I_main
.ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0"
.def _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc; .scl 2; .type 32; .endef
.def _ZNSolsEPFRSoS_E; .scl 2; .type 32; .endef
.def system; .scl 2; .type 32; .endef
.def _ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef
.def _ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef
.def atexit; .scl 2; .type 32; .endef
.section .rdata$.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, "dr"
.globl .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
.linkonce discard
.refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_:
.quad _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
.section .rdata$.refptr._ZSt4cout, "dr"
.globl .refptr._ZSt4cout
.linkonce discard
.refptr._ZSt4cout:
.quad _ZSt4cout
3、汇编
g++ -c name.cpp / name.s
使用g++ -c b.s对汇编代码进行汇编会生成相应的目标文件(b.o文件)
目标文件为二进制文件,由于尚未经过链接操作,所以无法直接运行。
4、链接
g++ b.o -o b.exe
将得到的b.o文件经过链接(一些函数和全局变量等)后便得到了可执行程序。
并不需要在g++添加任何选项,g++会在b.o的基础上完成链接操作。
参考链接:http://c.biancheng.net/view/7960.html
原文链接: https://www.cnblogs.com/dreammmz/p/13409800.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/201646
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!