真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

鏈接器的應(yīng)用(八)-創(chuàng)新互聯(lián)

    在上節(jié)博客中,我們介紹了鏈接器的相關(guān)概念。那么在本節(jié),我們就繼續(xù)來看看鏈接器,看看它在工程實(shí)踐中的應(yīng)用。我們在本節(jié)中做一個(gè)實(shí)驗(yàn),來模擬在嵌入式中的開發(fā)。

成都創(chuàng)新互聯(lián)是專業(yè)的呼中網(wǎng)站建設(shè)公司,呼中接單;提供成都網(wǎng)站建設(shè)、網(wǎng)站制作,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行呼中網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

        實(shí)驗(yàn)的目標(biāo):

                1、編寫一個(gè)“體積受限”的可執(zhí)行程序;

                2、通過 makefile 完成代碼編譯;

                3、運(yùn)行后在屏幕上打印“D.T.Software”

        那么這個(gè)目標(biāo)看似很簡單,我們在初學(xué)編程時(shí)就直接打印經(jīng)典的 hello world。其效果類似,經(jīng)典的代碼是

#include 

int main()
{
    printf("D.T.Software");
    
    return 0;
}

        當(dāng)然這個(gè)代碼也能運(yùn)行,但是我們的要求是體積受限。什么是體積受限呢?我們都知道,在嵌入式的開發(fā)中,內(nèi)存是很少的。因此節(jié)省內(nèi)存成立必不可少的因素,因此我們必須要去掉庫文件所包含的一些額外的信息,只保留打印語句所需要代碼即可。那么我們來深度分析下,如何進(jìn)行開發(fā)呢?無疑是直接用匯編代碼進(jìn)行編寫,然后編寫鏈接腳本自定義入口地址了。思路如下

鏈接器的應(yīng)用(八)

        由上可知,我們的解決方案可由以下幾部分完成:

                1、通過內(nèi)嵌匯編自定義打印函數(shù)和退出函數(shù)(INT 80H);

                2、通過鏈接腳本自定義入口函數(shù)(不依賴于任何庫和 GCC 內(nèi)置功能);

                3、刪除可執(zhí)行程序中的無用信息(無用段信息,調(diào)試信息等)。

        打印函數(shù)設(shè)計(jì)如下

void print(const char* s, int l)
{
    asm volatile (
        "movl $4, %%eax\n"    // sysy_write
        "movl $1, %%ebx\n"
        "movl %0, %%ecx\n"
        "movl %1, %%edx\n"
        "int $0x80     \n"    // 80H Service
        :
        : "r"(s), "r"(1)      // parameter
        : "eax", "ebx", "ecx", "edx");
}

        退出函數(shù)設(shè)計(jì)如下

void exit(int code)
{
    asm volatile (
        "movl $1, %%eax\n"    // sys_exit
        "movl %0, %%ebx\n"
        "int $0x80     \n"    // 80H Service
        :
        : "r"(code)             // parameter
        : "eax", "ebx");
}

        鏈接腳本設(shè)計(jì)如下

ENTRY(program)    // 指定入口函數(shù)

SECTIONS
{
    .text 0x08048000 + SIZEOF_HEADRS :
    {
        *(.text)    // 將目標(biāo)文件中的這兩個(gè)段合并進(jìn)入到可執(zhí)行程序中
        *(.rodata)
    }
    
    /DISCARD/ :
    {
        *(*)   // 放棄所有目標(biāo)文件中除 .test 和 .rodata 之外的其他段
    }
}

        最后來介紹幾個(gè)命令:

            1、ld 命令:GNU 的鏈接器,將目標(biāo)文件鏈接為可執(zhí)行程序;GCC 編譯器集中的一員。

            2、ld -static:表示 ld 使用靜態(tài)鏈接方式來產(chǎn)生最終程序,而不是采用默認(rèn)的動(dòng)態(tài)鏈接方式。

            3、gcc -fno-builtion:用于關(guān)閉 GCC 內(nèi)置函數(shù)的功能。


        在 GCC 中,它提供了很多內(nèi)置函數(shù)(Built-in Function),-fno-builtion 選項(xiàng)會(huì)把一些常用的 C 庫函數(shù)替換成編譯器的內(nèi)置函數(shù),以達(dá)到優(yōu)化的目的。

program.c 源碼

void print(const char* s, int l);
void exit(int code);

void program()
{
    print("D.T.Software\n", 13);
    exit(0);
}

void print(const char* s, int l)
{
    asm volatile (
        "movl $4, %%eax\n"           // 調(diào)用系統(tǒng)寫函數(shù),編號為 4
        "movl $1, %%ebx\n"           // 指定參數(shù),將字符串打印到屏幕
        "movl %0, %%ecx\n"           // 占位符,代表第一個(gè)參數(shù)(地址)
        "movl %1, %%edx\n"
        "int $0x80     \n"           // 開中斷 
        :                            // 輸入?yún)?shù)為空
        : "r"(s), "r"(l)             // 以只讀形式傳入?yún)?shù)
        : "eax", "ebx", "ecx", "edx" // 初始化寄存器
    );
}

void exit(int code)
{
    asm volatile (
        "movl $1, %%eax\n"
        "movl %0, %%ebx\n"
        "int $0x80     \n"
        :
        : "r"(code)
        : "eax", "ebx"
    );
}

makefile 編寫如下

CC := gcc
LD := ld
RM := rm -rf

TARGET := program.out
SRC := $(TARGET:.out=.c)
OBJ := $(TARGET:.out=.o)
LDS := $(TARGET:.out=.lds)

.PHONY : rebuild clean all

$(TARGET) : $(OBJ) $(LDS)
    $(LD) -static -T $(LDS) -o $@ $<
    @echo "Target File ==> $@"

$(OBJ) : $(SRC)
    $(CC) -fno-builtin -o $@ -c $^

rebuild : clean all

all : $(TARGET)

clean :
    $(RM) $(TARGET) $(OBJ)

        我們來運(yùn)行看看結(jié)果如何呢?

鏈接器的應(yīng)用(八)

        結(jié)果正是我們想要的,那么我們這么大費(fèi)周章的來寫這么復(fù)雜的代碼,究竟意義何在呢?我們來看看它的內(nèi)存大小,以及來編寫一個(gè)正常的 printf 打印語句的代碼,對比下兩個(gè)可執(zhí)行文件的內(nèi)存大小

鏈接器的應(yīng)用(八)

        我們看到效果是一樣的,但是正常的 printf 打印和我們自定義的鏈接腳本的函數(shù)編寫所需的內(nèi)存空間是十多倍的差異。也就是說,在嵌入式開發(fā)中,資源是很寶貴的這種做法是必須的。通過今天對鏈接腳本的實(shí)例分析,總結(jié)如下:1、對于資源受限的嵌入式設(shè)備,需要考慮可執(zhí)行程序的文件大??;2、通過內(nèi)嵌匯編直接使用系統(tǒng)服務(wù)能夠避開相關(guān)庫的使用;3、可以通過如下方法控制可執(zhí)行程序的體積大?。篴> 最小化庫的使用(必要情況下自己實(shí)現(xiàn)相關(guān)函數(shù));b> 自定義鏈接腳本,刪除無用段信息。


另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


分享名稱:鏈接器的應(yīng)用(八)-創(chuàng)新互聯(lián)
本文路徑:http://weahome.cn/article/hhhgh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部