.cpp文件是一个高级语言,这种形式容易被读懂。为了在系统上运行.cpp程序,每条c++语句都必须转化为低级的机器指令。然后将这些指令打包成可执行目标文件格式,并以二进制形式存储在磁盘中
gcc常用编译选项
选项 | 作用 |
-o | 产生目标(.i、.s、.o、可执行文件等) |
-c | 通知gcc取消链接步骤,即编译源码并在最后生成目标文件 |
-E | 只运行C预编译器 |
-S | 告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s |
-Wall | 使gcc对源文件的代码有问题的地方发出警告 |
-Idir | 将dir目录加入搜索头文件的目录路径 |
-Ldir | 将dir目录加入搜索库的目录路径 |
-llib | 链接lib库 |
-g | 在目标文件中嵌入调试信息,以便gdb之类的调试程序调试 |
以下代码示例是对函数模板(泛型编程)的反编译探究
结论:
1.编译器并不是把函数模板处理成能够处理任何任意类的函数
2.编译器从函数模板通过具体类型产生不同的函数
3.编译器会对函数模板进行两次编译
(在声明的地方对模板代码本身进行编译;在调用的地方再对参数替换后的代码进行编译。)
4.编译器在对函数模板编译时与调用的次数无关,与调用时参数类型有关
示例代码
#pragma warning(disable : 4996)
#include <iostream>
using namespace std;
template <typename T>
void MySwap(T &a, T &b)
{
T c = NULL;
c = a;
a = b;
b = c;
}
int main()
{
int a = 10;
int b = 20;
MySwap<int>(a, b);
MySwap(a, b);
printf("a:%d,b:%d \n", a, b);
char c = 'c';
char d = 'd';
MySwap<char>(c, d);
MySwap(c, d);
printf("c:%c,d:%c \n", c, d);
system("pause");
return 0;
}
通过命令行进行编译:g++ -S main.cpp -o main.s
.file "main.cpp"
.text
.section .rdata,"dr"
__ZStL19piecewise_construct:
.space 1
.lcomm __ZStL8__ioinit,1,1
.def ___main; .scl 2; .type 32; .endef
LC0:
.ascii "a:%d,b:%d \12\0"
LC1:
.ascii "c:%c,d:%c \12\0"
LC2:
.ascii "pause\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB1503:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $10, 28(%esp)
movl $20, 24(%esp)
leal 24(%esp), %eax
movl %eax, 4(%esp)
leal 28(%esp), %eax
movl %eax, (%esp)
call __Z6MySwapIiEvRT_S1_ //34 <==> 79
leal 24(%esp), %eax
movl %eax, 4(%esp)
leal 28(%esp), %eax
movl %eax, (%esp)
call __Z6MySwapIiEvRT_S1_ //39 <==> 79
movl 24(%esp), %edx
movl 28(%esp), %eax
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movb $99, 23(%esp)
movb $100, 22(%esp)
leal 22(%esp), %eax
movl %eax, 4(%esp)
leal 23(%esp), %eax
movl %eax, (%esp)
call __Z6MySwapIcEvRT_S1_ //52 <==> 110
leal 22(%esp), %eax
movl %eax, 4(%esp)
leal 23(%esp), %eax
movl %eax, (%esp)
call __Z6MySwapIcEvRT_S1_ //57 <==> 110
movzbl 22(%esp), %eax
movsbl %al, %edx
movzbl 23(%esp), %eax
movsbl %al, %eax
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $LC2, (%esp)
call _system
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1503:
.section .text$_Z6MySwapIiEvRT_S1_,"x"
.linkonce discard
.globl __Z6MySwapIiEvRT_S1_
.def __Z6MySwapIiEvRT_S1_; .scl 2; .type 32; .endef
__Z6MySwapIiEvRT_S1_:
LFB1739:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movl $0, -4(%ebp)
movl 8(%ebp), %eax
movl (%eax), %eax
movl %eax, -4(%ebp)
movl 12(%ebp), %eax
movl (%eax), %edx
movl 8(%ebp), %eax
movl %edx, (%eax)
movl 12(%ebp), %eax
movl -4(%ebp), %edx
movl %edx, (%eax)
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1739:
.section .text$_Z6MySwapIcEvRT_S1_,"x"
.linkonce discard
.globl __Z6MySwapIcEvRT_S1_
.def __Z6MySwapIcEvRT_S1_; .scl 2; .type 32; .endef
__Z6MySwapIcEvRT_S1_:
LFB1740:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movb $0, -1(%ebp)
movl 8(%ebp), %eax
movzbl (%eax), %eax
movb %al, -1(%ebp)
movl 12(%ebp), %eax
movzbl (%eax), %edx
movl 8(%ebp), %eax
movb %dl, (%eax)
movl 12(%ebp), %eax
movzbl -1(%ebp), %edx
movb %dl, (%eax)
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1740:
.text
.def ___tcf_0; .scl 3; .type 32; .endef
___tcf_0:
LFB1975:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $8, %esp
movl $__ZStL8__ioinit, %ecx
call __ZNSt8ios_base4InitD1Ev
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1975:
.def __Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
__Z41__static_initialization_and_destruction_0ii:
LFB1974:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
cmpl $1, 8(%ebp)
jne L8
cmpl $65535, 12(%ebp)
jne L8
movl $__ZStL8__ioinit, %ecx
call __ZNSt8ios_base4InitC1Ev
movl $___tcf_0, (%esp)
call _atexit
L8:
nop
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1974:
.def __GLOBAL__sub_I_main; .scl 3; .type 32; .endef
__GLOBAL__sub_I_main:
LFB1976:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $65535, 4(%esp)
movl $1, (%esp)
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1976:
.section .ctors,"w"
.align 4
.long __GLOBAL__sub_I_main
.ident "GCC: (MinGW.org GCC-8.2.0-3) 8.2.0"
.def _printf; .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