嵌入式—編譯器背後的故事

weixin_51087555發表於2020-10-15

一、可執行程式的組裝

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)遊戲執行
在這裡插入圖片描述

四、總結

此次任務較多,實仿較簡單,安裝過程遇到了一些困難,整個過程持續時間較長。

相關文章