.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