嵌入式—編譯器背後的故事
編譯器背後的故事
一、可執行程式的組裝
1.用gcc生成靜態庫和動態庫
(1) 第 1 步:編輯生成例子程式 hello.h、hello.c 和 main.c。
先建立一個作業目錄,儲存本次練習的檔案。
#mkdir test1
#cd test1
然後用 vim文字編輯器編輯生成所需要的 3 個檔案。
程式1:
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
程式2:
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
程式3:
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
(2) 第 2 步:將 hello.c 編譯成.o 檔案。
在系統提示符下鍵入以下命令得到 hello.o 檔案。
gcc -c hello.c
我們執行 ls 命令看看是否生存了 hello.o 檔案
在 ls 命令結果中,我們看到了 hello.o 檔案
(3) 第 3 步:由.o 檔案建立靜態庫。
建立靜態庫用 ar 命令。在系統提示符下鍵入以下命令將建立靜態庫檔案 libmyhello.a。
ar -crv libmyhello.a hello.o
我們同樣執行 ls 命令檢視結果:
ls
hello.c hello.h hello.o libmyhello.a main.c
(4) 第 4 步:在程式中使用靜態庫。
下面先生成目標程式 hello,然後執行 hello 程式。
# gcc -o hello main.c -L. –lmyhello
執行結果
刪除靜態庫檔案
# rm libmyhello.a
rm: remove regular file `libmyhello.a'? y
# ./hello
Hello everyone!
#
程式照常執行
在 Linux 中建立動態庫
(5) 第 5 步:由.o 檔案建立動態庫檔案
在系統提示符下鍵入以下命令得到動態庫檔案 libmyhello.so
gcc -shared -fPIC -o libmyhello.so hello.o
使用is命令
# ls
hello.c hello.h hello.o libmyhello.so main.c
(6) 第 6 步:在程式中使用動態庫
我們先執行 gcc 命令生成目標檔案,再執行
# gcc -o hello main.c -L. -lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory
執行結果
再來建立靜態庫檔案 libmyhello.a 和動態庫檔案 libmyhello.so
# gcc -c hello.c
# ar -cr libmyhello.a hello.o (或-cvr )
# gcc -shared -fPIC -o libmyhello.so hello.o
# ls
hello.c hello.h hello.o libmyhello.a libmyhello.so main.c
執行 gcc 命令來使用函式庫 myhello 生成目標檔案 hello,並執行程式 hello
# gcc -o hello main.c -L. –lmyhello
# ./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shar
ed object file: No such file or directory
2.靜態庫應用
除了x2x函式之外,再擴充套件寫一個x2y函式(功能自定),main函式程式碼將呼叫x2x和x2y ;將這3個函式分別寫成單獨的3個 .c檔案,並用gcc分別編譯為3個.o 目標檔案;將x2x、x2y目標檔案用 ar工具生成1個 .a 靜態庫檔案, 然後用 gcc將 main函式的目標檔案與此靜態庫檔案進行連結,生成最終的可執行程式,記錄檔案的大小
(1)建立檔案
#gedit sub1.c
#gedit sub2.c
#gedit main.c
(2)函式的編寫
sub1.c
float x2x(float a, float b) {
return a * b;
}
sub2.c
float x2y(float a, float b) {
return a - b;
}
main.c
#include<stdio.h>
extern float x2x(float a, float b);
extern float x2y(float a, float b);
int main() {
float a = 3;
float b = 2;
printf("ax2xb=%f\n",x2x(a,b));
printf("ax2yb=%f\n",x2y(a,b));
}
(3)編譯.o檔案並建立連線
#gcc -c sub1.c
#gcc -c sub2.c
#gcc -c main.c
ls
執行結果
(4)生成靜態庫檔案
#ar -crv 1.a sub1.o sub2.o
程式結果
檔案大小
3.動態庫應用
(1)建立檔案
#rm 1.a
#rm sub1
ls
(2)建立動態庫檔案連結
#gcc -shared -fPIC -o 2.so sub1.o sub2.o
執行結果
4.總結
以上可見,靜態庫的檔案大小略大於動態庫的檔案大小
二、Gcc不是一個人在戰鬥
1.Linux Gcc常用命令
(1)編譯
//test.c
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
(2)預處理
gcc -E test.c -o test.i
執行結果
(3)編譯為彙編程式碼
gcc -S test.i -o test.s
(4)彙編
gcc -c test.s -o test.o
(5)連線
gcc test.o -o test
(6)多個程式檔案的編譯
假設有一個由 test1.c 和 test2.c 兩個原始檔組成的程式,為了對它們進行編譯,並最終生成可執行程式 test,可以使用下面這條命令:
gcc test1.c test2.c -o test
如果同時處理的檔案不止一個,深究起來,上面這條命令大致相當於依次執行如下三條命令:
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test
(7)檢錯
gcc -pedantic illcode.c -o illcode
除了-pedantic 之外,GCC 還有一些其它編譯選項也能夠產生有用的警告資訊。這些選項大多以-W 開頭,其中最有價值的當數-Wall 了,使用它能夠使 GCC 產生儘可能多的警告資訊。
gcc -Wall illcode.c -o illcode
在編譯程式時帶上-Werror 選項,那麼 GCC 會在所有產生警告的地方停止編譯,迫使程式設計師對自己的程式碼進行修改,如下:
gcc -Werror test.c -o test
執行結果
(8)庫檔案連線
編譯可執行檔案
gcc –c –I /usr/dev/mysql/include test.c –o test.o
連線
gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test
(9)強制連結時使用靜態連結庫
預設情況下, GCC 在連結時優先使用動態連結庫,只有當動態連結庫不存在時才考慮使用靜態連結庫,如果需要的話可以在編譯時加上-static 選項,強制使用靜態連結庫。
在/usr/dev/mysql/lib 目錄下有連結時所需要的庫檔案 libmysqlclient.so 和 libmysqlclient.a,為了讓GCC 在連結時只用到靜態連結庫,可以使用下面的命令:
gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test
2.nasm安裝和應用
(1)安裝
sudo apt-get install nasm//安裝nasm
nasm -version//檢視版本
(2)應用
編譯
nasm -f elf64 hello.asm
連線
ld -s -o hello hello.o
執行
./hello
執行結果
nasm比gcc生成的檔案要小
三、藉助第三方庫函式完成程式碼設計
1.游標庫
函式名 | 功能 |
---|---|
initscr() | 初始化curses庫和tty |
endwin() | 關閉curses並重置tty |
refresh() | 使螢幕按照你的意圖顯示 |
addstr(s) | 在當前位置畫字串s |
addch(c) | 在當前位置畫字元c |
clear() | 清屏 |
2.BBS
在 win10 系統中,“控制皮膚”–>“程式”—>“啟用或關閉Windows功能”,啟用 “telnet client” 和"適用於Linux的Windows子系統"(後面會使用)。 然後開啟一個cmd命令列視窗,命令列輸入 telnet bbs.newsmth.net,以遊客身份體驗一下即將絕跡的遠古時代的 BBS
3.安裝curses庫
程式碼如下
sudo apt-get install libncurses5-dev
安裝完成
4.貪吃蛇遊戲
(1)建立檔案
(2)遊戲執行
四、總結
此次任務較多,實仿較簡單,安裝過程遇到了一些困難,整個過程持續時間較長。
相關文章
- GCC編譯器背後的故事GC編譯
- 編譯器背後的故事(入門練習)編譯
- Redis持久化背後的故事Redis持久化
- dyld背後的故事&原始碼分析原始碼
- 愛回收IPO背後的新老故事
- RestCloud ETL 社群版背後的故事RESTCloud
- 郭超:阿里雲Cassandra背後的故事阿里
- 編譯器後端總結編譯後端
- 蘋果自動駕駛背後的故事蘋果自動駕駛
- 安能物流 All in TiDB 背後的故事與成果TiDB
- 請求 www.baidu.com 背後的故事AI
- 誰來背鍋?自動駕駛車禍背後的故事自動駕駛
- 更好的 java 重試框架 sisyphus 背後的故事Java框架
- 【前端軼事】Chrome 小恐龍背後的故事前端Chrome
- 聊聊百度搜尋背後的故事
- 開源筆記軟體 Joplin 背後的故事筆記
- 4399《胡偵探傳說》系列背後的故事
- xjbz京東電器攜肖戰獻上賀歲大片《後背》,講述冠軍背後的守護故事
- 騰訊與Github的魔幻會面背後的故事…Github
- [譯] Service workers:PWA背後的英雄
- [譯] ? styled-components 背後的魔法
- 《碼出高效:Java開發手冊》背後的故事Java
- CVE-2016-1779技術分析及其背後的故事
- 《百英雄傳》眾籌450萬美元背後的故事
- What CANN Can?一輛小車背後的智慧故事
- 我們的20年 | 講述雲安全背後的故事
- 滑鼠打字的背後,隱藏著一個感人的故事
- JIT編譯器推導求餘%上下界引發的一連串故事編譯
- 揭祕電子遊戲背後音效製作的故事遊戲
- 為你揭祕小程式音視訊背後的故事......
- 微信支付商戶系統架構背後的故事架構
- 專利背後的故事 | 一種郵件安全控制方法
- 一段《生化危機》音效背後的離奇故事
- 編譯器的自展和自舉、交叉編譯編譯
- 淺談彙編器、編譯器和直譯器編譯
- 2022 GDC EGW分享:《時之形》創作背後故事
- [譯] Service workers:Progressive Web Apps 背後的小英雄WebAPP
- 功能遊戲爆款的誕生之路,《家國夢》背後的故事遊戲