1 新建一個(gè)文件test,代碼如下:
#include <stdio.h> int main(void) { printf("Hello World!\n"); return 0; }
直接編譯指令如下:
gcc test.c -o test
實(shí)際上編譯過(guò)程有四個(gè)階段,即預(yù)處理(也稱預(yù)編譯,Preprocessing)、編譯 (Compilation)、匯編 (Assembly)和連接(Linking)。
2 編譯過(guò)程
2.1 預(yù)處理
gcc -E test.c -o test.i 或 gcc -E test.c
gcc 的-E 選項(xiàng),可以讓編譯器在預(yù)處理后停止,并輸出預(yù)處理結(jié)果。
2.2 編譯為匯編代碼(Compilation)
gcc -S test.i -o test.s
gcc 的-S 選項(xiàng),表示在程序編譯期間,在生成匯編代碼后,停止,-o 輸出匯編代碼文件。
2.3 匯編(Assembly)
gcc -c test.s -o test.o
gas 匯編器負(fù)責(zé)將test.s編譯為目標(biāo)文件。
2.4 連接(Linking)
gcc test.o -o test
gcc 連接器將程序的目標(biāo)文件與所需的所有附加的目標(biāo)文件(靜態(tài)連接庫(kù)和動(dòng)態(tài)連接庫(kù))連接起來(lái),最終生 成可執(zhí)行文件。
2.5 執(zhí)行命令
./test
顯示如下:
3.1編譯由test1.c 和 test2.c 兩個(gè)源文件組成的程序
gcc test1.c test2.c -o test
3.2當(dāng)需要處理多個(gè)文件,GCC 編譯過(guò)程:預(yù)處理、編譯和鏈接依次進(jìn)行
gcc -c test1.c -o test1.o gcc -c test2.c -o test2.o gcc test1.o test2.o -o test
4 檢錯(cuò)
4.1 -pedantic 編譯選項(xiàng)
gcc -pedantic illcode.c -o illcode
-pedantic 選項(xiàng)無(wú)法發(fā)現(xiàn)全部錯(cuò)誤,只能發(fā)現(xiàn)一些不符合 ANSI/ISO C 標(biāo)準(zhǔn)的代碼。
4.2 Wall 編譯選項(xiàng)
gcc -Wall illcode.c -o illcode
4.3-Werror 選項(xiàng)
gcc -Werror test.c -o test
GCC 會(huì)在所有產(chǎn)生警告的地方停止編譯。
5 庫(kù)文件連接
庫(kù)文件包括頭文件(.h)和庫(kù)文件(so、或 lib、dll)等;位于/usr/lib/目錄下。主要有兩類,分別是是動(dòng)態(tài)鏈接庫(kù)(.so)和靜態(tài)鏈接庫(kù)(.a)。
5.1 編譯成可執(zhí)行文件
gcc –c –I /usr/dev/mysql/include test.c –o test.o
5.2 鏈接
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
5.3 強(qiáng)制鏈接時(shí)使用靜態(tài)鏈接庫(kù)
-static 選項(xiàng)
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
1.GCC的戰(zhàn)友
1.1 Binutils是一組二進(jìn)制程序處理工具,主要有:addr2line、ar、objcopy、objdump、as、ld、 ldd、readelf、 size 等;
(1) addr2line:幫助調(diào)試器在調(diào)試的過(guò)程中定位對(duì)應(yīng)的源代碼位置。
(2) as:用于匯編;
(3) ld:用于鏈接;
(4) ar:用于創(chuàng)建靜態(tài)庫(kù)。
1.2 C 運(yùn)行庫(kù)
(1)C 的語(yǔ)法;
(2)另一部分描述 C 標(biāo)準(zhǔn)庫(kù)。
2.編譯過(guò)程
2.1事先編譯一個(gè)hello.c源程序,代碼如下:
#include <stdio.h>int main(void) { printf("Hello World! \n"); return 0; }
2.2預(yù)處理命令,生成hello.i文件
gcc -E hello.c -o hello.i
2.3編譯命令,生成hello.s文件(此時(shí)已經(jīng)為匯編代碼)
gcc -S hello.i -o hello.s
2.4匯編命令,將編譯生成的 hello.s 文件匯編生成目標(biāo)文件 hello.o
gcc -c hello.s -o hello.o
或調(diào)用 as 進(jìn)行匯編
as -c hello.s -o hello.o
此時(shí)hello.o 目標(biāo)文件為 ELF(Executable and Linkable Format)格式的可重定向文件。
2.5鏈接,將目標(biāo)文件 hello.o生成 ELF 格式可執(zhí)行文件
$ gcc hello.c -o hello
此時(shí)為動(dòng)態(tài)鏈接。
gcc -static hello.c -o hello
此時(shí)為靜態(tài)鏈接。
ELF 文件格式包含
1 .text:已編譯程序的指令代碼段;
2 .rodata:ro 代表 read only,即只讀數(shù)據(jù)(譬如常數(shù) const);
3 .data:已初始化的 C 程序全局變量和靜態(tài)局部變量;
4.bss:未初始化的 C 程序全局變量和靜態(tài)局部變量;
5 .debug:調(diào)試符號(hào)表,調(diào)試器用此段的信息幫助調(diào)試。
可以使用如下代碼查看匯編ELF各個(gè)部分:
readelf -S
可以使用如下代碼查看反匯編ELF各個(gè)部分:
objdump -D
3.匯編語(yǔ)言格式(.asm)
由于在ubantu下的匯編代碼是Intel風(fēng)格的,此時(shí)可以用nasm匯編編譯器編譯生成執(zhí)行程序。
3.1安裝nasm匯編編輯器
輸入如下命令
sudo apt install nasm
sudo apt-get update
sudo apt install nasm
; hello.asm section .data ; 數(shù)據(jù)段聲明 msg db "Hello, world!", 0xA ; 要輸出的字符串 len equ $ - msg ; 字串長(zhǎng)度section .text ; 代碼段聲明global _start ; 指定入口函數(shù)_start: ; 在屏幕上顯示一個(gè)字符串 mov edx, len ; 參數(shù)三:字符串長(zhǎng)度 mov ecx, msg ; 參數(shù)二:要顯示的字符串 mov ebx, 1 ; 參數(shù)一:文件描述符(stdout) mov eax, 4 ; 系統(tǒng)調(diào)用號(hào)(sys_write) int 0x80 ; 調(diào)用內(nèi)核功能 ; 退出程序 mov ebx, 0 ; 參數(shù)一:退出代碼 mov eax, 1 ; 系統(tǒng)調(diào)用號(hào)(sys_exit) int 0x80 ; 調(diào)用內(nèi)核功能
3.3由hello.asm生成可執(zhí)行文件,輸入如下命令
nasm -f elf64 hello.asmld -s -o hello hello.o./hello
以上就是本文的全部?jī)?nèi)容,主要介紹了GCC的一些常用工具,命令,以及匯編語(yǔ)言在ubantu下的使用。
聯(lián)系客服