知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產生價值,我們在追求其視覺表現(xiàn)的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
XX的學習日記(嵌入式)三——編譯器背后的故事
發(fā)表時間:2020-10-19
發(fā)布人:葵宇科技
瀏覽次數(shù):47
編譯器背后的故事
- 一、可執(zhí)行程序是如何被組裝的?
- 1. 用 gcc 生成 .a 靜態(tài)庫和 .so 動態(tài)庫
- 1.1 編輯得到舉例的程序:hello.h、hello.c和main.c
- 1.2 將hello.c編譯成.o文件;
- 1.3由.o文件創(chuàng)建靜態(tài)庫
- 1.4 在程序中使用靜態(tài)庫
- 1.5由.o文件創(chuàng)建動態(tài)庫文件
- 1.6 在程序中使用動態(tài)庫
- 2.Linux下靜態(tài)庫.a與.so庫文件的生成與使用
- 2.1 編輯所需程序
- 2.1 靜態(tài)庫.a文件的生成與使用
- 2.2 共享庫.so文件的生成與使用
- 3. 將第一次學習內容的程序進行改編
- 3.1 完成目標(1)
- 3.2 完成目標(2)
- 二、Gcc不是一個人在戰(zhàn)斗。
- 1. Linux GCC常用命令
- 1.1 程序準備
- 1.2 程序的簡單編譯
- 1.3 程序的分步編譯
- 2. 比較hello.asm與C代碼生成的可執(zhí)行文件
- 2.1 搭建環(huán)境:在Ubuntu上安裝nasm
一、可執(zhí)行程序是如何被組裝的?
1. 用 gcc 生成 .a 靜態(tài)庫和 .so 動態(tài)庫
我們通常把一些公用函數(shù)制作成函數(shù)庫,供其它程序使用。函數(shù)庫分為靜態(tài)庫和動態(tài)庫兩種。靜態(tài)庫在程序編譯時會被連接到目標代碼中,程序運行時將不再需要該靜態(tài)庫。動態(tài)庫在程序編譯時并不會被連接到目標代碼中,而是在程序運行是才被載入,因此在程序運行時還需要動態(tài)庫存在。
我們通過舉例來說明在Linux中如何創(chuàng)建靜態(tài)庫和動態(tài)庫,以及使用它們,在創(chuàng)建函數(shù)庫前,我們先來準備舉例用的源程序,并將函數(shù)庫的源程序編譯成.o文件。
1.1 編輯得到舉例的程序:hello.h、hello.c和main.c
hello.c是函數(shù)庫的源程序,其中包含公用函數(shù)hello,該函數(shù)將在屏幕上輸出"Hello XXX!"。hello.h為該函數(shù)庫的頭文件。main.c為測試庫文件的主程序,在主程序中調用了公用函數(shù)hello。
hello.h
hello.c
main.c
1.2 將hello.c編譯成.o文件;
無論靜態(tài)庫,還是動態(tài)庫,都是由.o文件創(chuàng)建的。因此,我們必須將源程序hello.c通過gcc先編譯成.o文件。
在系統(tǒng)提示符下鍵入以下命令得到hello.o文件。
gcc -c hello.c
通過ls命令查看是否生成了hello.o文件
1.3由.o文件創(chuàng)建靜態(tài)庫
靜態(tài)庫文件名的命名規(guī)范是以lib為前綴,緊接著跟靜態(tài)庫名,擴展名為.a。例如:我們將創(chuàng)建的靜態(tài)庫名為myhello,則靜態(tài)庫文件名就是libmyhello.a。在創(chuàng)建和使用靜態(tài)庫時,需要注意這點。創(chuàng)建靜態(tài)庫用ar命令。
在系統(tǒng)提示符下鍵入以下命令將創(chuàng)建靜態(tài)庫文件libmyhello.a,并用ls命令查看結果
ar -crv libmyhello.a hello.o
1.4 在程序中使用靜態(tài)庫
靜態(tài)庫制作完了,如何使用它內部的函數(shù)呢?只需要在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明靜態(tài)庫名,gcc將會從靜態(tài)庫中將公用函數(shù)連接到目標文件中。注意,gcc會在靜態(tài)庫名前加上前綴lib,然后追加擴展名.a得到的靜態(tài)庫文件名來查找靜態(tài)庫文件。
在程序3:main.c中,我們包含了靜態(tài)庫的頭文件hello.h,然后在主程序main中直接調用公用函數(shù)hello。下面先生成目標程序hello,然后運行hello程序看看結果如何。
我們輸入以下指令:gcc main.c libmyhello.a -o hello
我們刪除靜態(tài)庫文件試試公用函數(shù)hello是否真的連接到目標文件 hello中了。
(這里我打錯了一段指令,馬了別介意: D)
程序照常運行,靜態(tài)庫中的公用函數(shù)已經連接到目標文件中了。
1.5由.o文件創(chuàng)建動態(tài)庫文件
我們繼續(xù)看看如何在Linux中創(chuàng)建動態(tài)庫。我們還是從.o文件開始。
動態(tài)庫文件名命名規(guī)范和靜態(tài)庫文件名命名規(guī)范類似,也是在動態(tài)庫名增加前綴lib,但其文件擴展名為.so。例如:我們將創(chuàng)建的動態(tài)庫名為myhello,則動態(tài)庫文件名就是libmyhello.so。用gcc來創(chuàng)建動態(tài)庫。
在系統(tǒng)提示符下鍵入以下命令得到動態(tài)庫文件libmyhello.so,并用ls命令查看
gcc -shared -fPIC -o libmyhello.so hello.o (-o不可少)
1.6 在程序中使用動態(tài)庫
在程序中使用動態(tài)庫和使用靜態(tài)庫完全一樣,也是在使用到這些公用函數(shù)的源程序中包含這些公用函數(shù)的原型聲明,然后在用gcc命令生成目標文件時指明動態(tài)庫名進行編譯。我們先運行gcc命令生成目標文件,再運行它看看結果。
輸入以下指令:gcc -o hello main.c -L. -lmyhello
這里出現(xiàn)了錯誤,我們看看錯誤提示,原來是找不到動態(tài)庫文件libmyhello.so。程序在運行時,會在/usr/lib和/lib等目錄中查找需要的動態(tài)庫文件。若找到,則載入動態(tài)庫,否則將提示類似上述錯誤而終止程序運行。我們將文件libmyhello.so復制到目錄/usr/lib中,再試試。
2.Linux下靜態(tài)庫.a與.so庫文件的生成與使用
如前面一樣,我們先生成舉例所需要的文件
2.1 編輯所需程序
A1.c
A2.c
A.h
test.c
2.1 靜態(tài)庫.a文件的生成與使用
(1) 生成目標文件(XXX.o)
指令如下:gcc -c A1.c A2.c
(2)生成靜態(tài)庫.a文件
指令如下:ar crv libafile.a A1.o A2.o
(3)使用.a 庫文件,創(chuàng)建可執(zhí)行程序(若采用此種方式,需保證生成的.a 文件與.c 文件保存在同一目錄下,即都在當前目錄下)
指令如下:
cpp gcc -o test test.c libafile.a
./test
2.2 共享庫.so文件的生成與使用
(1)生成目標文件(XXX.o)(此處生成.o 文件必須添加"-fpic"(小模式,代碼少),否則在生成.so文件時會出錯)
指令:gcc -c -fpic A1.c A2.c
(2)生成共享庫.so文件
指令:gcc -shared *.o -o libsofile.so
(3)使用.so 庫文件,創(chuàng)建可執(zhí)行程序
指令:gcc -o test test.c libsofile.s
當輸入以下指令時:./test
發(fā)現(xiàn)出現(xiàn)錯誤:
原因與之前使用動態(tài)庫的情況相同:找不到對用的.so文件,故需將對應 so 文件拷貝到對應路徑。
指令
如下:sudo cp libsofile.so /usr/lib
同時可直接使用 gcc -o test test.c -L. -lname,來使用相應庫文件
其中,
-L.:表示在當前目錄下,可自行定義路徑 path,即使用-Lpath 即可。
-lname:name:即對應庫文件的名字(除開 lib),即若使用 libafile.a,則 name 為 afile;若要使用 libsofile.so,則 name 為 sofile。
3. 將第一次學習內容的程序進行改編
目標:
(1)除了x2x函數(shù)之外,再擴展寫一個x2y函數(shù)(功能自定),main函數(shù)代碼將調用x2x和x2y ;將這3個函數(shù)分別寫成單獨的3個 .c文件,并用gcc分別編譯為3個.o 目標文件;將x2x、x2y目標文件用 ar工具生成1個 .a 靜態(tài)庫文件, 然后用 gcc將 main函數(shù)的目標文件與此靜態(tài)庫文件進行鏈接,生成最終的可執(zhí)行程序,記錄文件的大小。
(2)將x2x、x2y目標文件用 ar工具生成1個 .so 動態(tài)庫文件, 然后用 gcc將 main函數(shù)的目標文件與此動態(tài)庫文件進行鏈接,生成最終的可執(zhí)行程序,記錄文件的大小,并與之前做對比。
3.1 完成目標(1)
(1)編輯所需程序
x2x.c
x2y.c
main.c
(2)將以上文件用gcc編譯成.o文件
(3)將x2x.o和x2y.o用 ar工具生成 .a 靜態(tài)庫文件
(4)使用gcc將main.c文件與此靜態(tài)庫文件進行鏈接
(5) 運行xymain程序
記錄文件大小為16888B
3.2 完成目標(2)
(1)將x2x.o、x2y.o文件用ar工具生成.so 動態(tài)庫文件
(2)用gcc將main.c文件與此動態(tài)庫文件進行鏈接
(3)運行somain
記錄文件大小為16888B
二、Gcc不是一個人在戰(zhàn)斗。
GCC 的意思也只是 GNU C Compiler 而已。經過了這么多年的發(fā)展,GCC 已經不僅僅能支持 C語言;它現(xiàn)在還支持 Ada 語言、C++ 語言、Java 語言、Objective C 語言、Pascal 語言、COBOL語言,以及支持函數(shù)式編程和邏輯編程的 Mercury 語言,等等。而 GCC 也不再單只是 GNU C 語言編譯器的意思了,而是變成了 GNU Compiler Collection 也即是 GNU 編譯器家族的意思了。另一方面,說到 GCC 對于操作系統(tǒng)平臺及硬件平臺支持,概括起來就是一句話:無所不在。
1. Linux GCC常用命令
1.1 程序準備
1.2 程序的簡單編譯
這個程序的一步到位的編譯指令是gcc test.c -o main
1.3 程序的分步編譯
實質上,上述編譯過程是分為四個階段進行的,即預處理(也稱預編譯,Preprocessing)、編譯(Compilation)、匯編 (Assembly)和連接(Linking)。
gcc -E test.c -o test.i //預處理
gcc -S test.i -o test.s //編譯
gcc -c test.s -o test.o //匯編
gcc test.o -o test //連接
執(zhí)行以上指令后生成以下文件,并查看運行結果
2. 比較hello.asm與C代碼生成的可執(zhí)行文件
2.1 搭建環(huán)境:在Ubuntu上安裝nasm
相關案例查看更多
相關閱讀
- 汽車報廢回收管理軟件
- 迪慶小程序開發(fā)
- 云南網(wǎng)站建設百度官方
- SEO
- 網(wǎng)站建設招商
- python開發(fā)小程序
- 網(wǎng)站收錄
- 網(wǎng)絡公司哪家好
- 汽車報廢管理系統(tǒng)
- 云南網(wǎng)站優(yōu)化公司
- 制作一個小程序
- 云南小程序公司
- 云南小程序開發(fā)課程
- 云南網(wǎng)站建設費用
- 網(wǎng)站建設需要多少錢
- 小程序的開發(fā)公司
- 云南網(wǎng)站建設優(yōu)化
- 正規(guī)網(wǎng)站建設公司
- APP
- 百度小程序開發(fā)公司
- 江蘇小程序開發(fā)
- 云南小程序開發(fā)推薦
- 二叉樹
- 電商網(wǎng)站建設
- 昆明小程序設計
- 云南etc微信小程序
- 網(wǎng)站排名優(yōu)化
- 云南小程序開發(fā)費用
- asp網(wǎng)站
- 網(wǎng)站建設方案 doc