0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

C語言生成可執(zhí)行二進制文件的具體過程

小杜的芯片驗證日記 ? 來源:數(shù)字芯片驗證日記 ? 2024-10-21 14:30 ? 次閱讀

Hi,我是小杜。SoC驗證中會經(jīng)常使用C語言,所以需要知道C語言生成可執(zhí)行二進制文件的具體過程以及如何從生成的中間文件讀取有用信息。因為小杜是轉行做數(shù)字IC驗證,SoC的知識需要重頭開始學,如果錯誤,還請批評指正。

C語言源碼到生成可執(zhí)行文件的過程通常包括預處理(Preprocessing)、編譯(Compilation)匯編(Assembly)、鏈接(Linking)等多個步驟,每個步驟都有其特定的任務和產(chǎn)物。下面,小杜通過一個具體的例子詳細講述這個過程,以及如何通過反匯編(Disassembly)來查看匯編、鏈接產(chǎn)生的不可讀二進制目標文件。

C語言源碼準備

首先編寫3個文件,一個是主程序 main.c,另一個是功能函數(shù) func.c,外加一個頭文件 func.h。具體路徑為:

project/
│
├──main.c
├── func.c
└── func.h

代碼如下:

// main.c
#include 
#include


int main() {
    int result = add(5, 3);
    printf("Result: %d
", result);
    return 0;
}
// func.c
#include "func.h"


int add(int a, int b) {
    return a + b;
}
// func.h
#ifndef FUNC_H
#define FUNC_H


int add(int a, int b);


#endif

分步生成可執(zhí)行文件

1. 預處理(Preprocessing)

處理器處理 #include、#define 等指令,并生成一個預處理后的文件??梢允褂?-E 選項運行預處理器。

gcc-Emain.c-omain.i-I .
gcc-Efunc.c-ofunc.i-I .

main.i 和 func.i 是預處理后的文件,包含展開后的宏和頭文件內(nèi)容。以main.i為例,預處理后的文件可能會非常長,因為所有的宏、頭文件都被展開。預處理器在預處理文件中插入了很多#開頭的行,提供了文件和行號信息用于調(diào)試和錯誤報告。下面截圖展示了main.i文件中的主要部分:

d77efbbada0c87c9d2452c4697b7a758.png

源碼中所有的注釋都會在預處理階段被去除。如果源碼中有條件編譯指令,比如`ifdef,`ifndef,`if 等,預處理器會根據(jù)條件和結果保留或刪除相應的代碼。

預處理文件的用途

調(diào)試:通過查看預處理后的文件,可以檢查宏和頭文件是否正確展開,從而幫助調(diào)試編譯問題。

了解代碼結構:預處理文件展示了代碼的最終形態(tài),包括所有的頭文件和宏定義,這對理解代碼的整體結構很有幫助。

性能優(yōu)化:分析預處理后的代碼,有助于識別和優(yōu)化編譯時間和代碼冗余問題。

2.編譯(Compilation)

編譯器將預處理后的C代碼轉換為匯編代碼。可以使用 -S 選項生成匯編代碼。

gcc -s main.i -o main.s -I .
gcc-sfunc.i -o func.s -I .

231418c4da982fbcdf43578c09ee96bf.png

從生成的匯編代碼中我們可以看到文件和段定義、函數(shù)入口和棧幀設置調(diào)用add函數(shù)、調(diào)用printf函數(shù)以及函數(shù)退出。

匯編代碼可能是調(diào)試過程中接觸的最底層部分,SoC驗證過程中如果CPU卡死,通過記錄的寄存器內(nèi)容、程序計數(shù)器(PC)和堆棧指針(SP),找到對應的匯編指令就可以知道CPU卡死的具體位置,這對調(diào)試和找出代碼bug十分重要。從匯編代碼中我們可以得到如下信息:

函數(shù)調(diào)用和參數(shù)傳遞

通過匯編代碼可以看到函數(shù)是如何調(diào)用的,以及參數(shù)是如何傳遞的。例如,在x86-64架構中,前六個整數(shù)參數(shù)通過寄存器(如EDI、ESI、EDX等)傳遞。

棧幀管理

匯編代碼展示了棧幀是如何創(chuàng)建和銷毀的,尤其是通過 pushq %rbp、movq %rsp, %rbp 和 leave 指令。這有助于理解函數(shù)調(diào)用過程中棧的變化。

變量和寄存器操作
匯編代碼展示了如何使用寄存器和內(nèi)存操作來實現(xiàn)程序邏輯。例如,通過 movl 指令可以看到如何在寄存器和內(nèi)存之間傳遞數(shù)據(jù)。

調(diào)試和優(yōu)化

通過分析匯編代碼,可以發(fā)現(xiàn)編譯器生成的代碼是否高效。例如,可以識別不必要的指令或冗余操作,進而優(yōu)化代碼。

3. 匯編(Assembly)與反匯編(Disassembly)

匯編器將匯編代碼轉換為機器碼,生成目標文件。可以使用 -c 選項生成目標文件。這一步開始生成的二進制目標文件已經(jīng)不能看了,不過我們還是可以通過反匯編來獲取有用信息。

gcc -c main.s -o main.o -I .
gcc-cfunc.s-ofunc.o -I .

fa89308c9cb7370bccd12364056881b3.jpg

main.o 和func.o 是目標文件,包含機器代碼、符號表和調(diào)試信息,但它們是二進制格式,不像匯編代碼那樣直接可讀。我們可以使用工具來查看分析目標文件,以獲取有用的信息,比如使用objdump。

反匯編

通過反匯編可以查看目標文件的機器碼、段信息以及符號表。

objdump-dmain.o#反匯編目標文件,顯示機器碼
objdump-hmain.o#顯示目標文件的段信息
objdump -t main.o # 顯示符號表

比如反匯編產(chǎn)生機器碼(工作中一般不會接觸這么深,這里只是舉例):

11cf077e50f573983ed7897c960189a5.png

4. 鏈接(Linking)

鏈接器將多個目標文件和庫文件鏈接在一起,生成最終的可執(zhí)行文件。

gccmain.ofunc.o-omyprogram

65949ea6b1f1e83e7bd9af8eff7a256d.png

myprogram 是最終生成的可執(zhí)行文件。二進制可執(zhí)行文件不可讀,但同樣可以使用objdump來查看可執(zhí)行文件的有用信息,比如:

objdump -f myprogram # 查看可執(zhí)行文件功能

該輸出展示了可執(zhí)行文件的基本信息,包括文件格式、架構、標志和程序入口信息。

5a89bd9fb1e5320b578b1595d47f5580.png

一步到位的編譯和鏈接

通常我們會直接使用 gcc 命令來一步到位完成整個過程,而不需要手動執(zhí)行每個步驟:

gccmain.cfunc.-omyprogram

這個命令會自動處理上述所有步驟,并生成最終的可執(zhí)行文件 myprogram。

總結 讓我們來總結一下C語言源碼到最終的可執(zhí)行二進制文件的4個過程分別干了哪些事:

預處理:處理頭文件包含和宏定義,生成一個單一的C源文件。

編譯:將C源文件轉換為匯編代碼,這一步會進行語法檢查和優(yōu)化。

匯編:將匯編代碼轉換為目標文件,目標文件是二進制格式的機器碼,但還不是完整的可執(zhí)行程序。

鏈接:將多個目標文件和庫文件鏈接在一起,解決符號引用問題(如函數(shù)和變量的定義和聲明),生成最終的可執(zhí)行文件。

感謝你看到這里。項目工作中,其實工具鏈建立好之后一般也就不會去關注這些過程了,寫完C代碼走腳本流程即可,但如果出現(xiàn)bug,了解這一過程對解決bug就很重要了!

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 二進制
    +關注

    關注

    2

    文章

    778

    瀏覽量

    41557
  • C語言
    +關注

    關注

    180

    文章

    7591

    瀏覽量

    135788
  • 函數(shù)
    +關注

    關注

    3

    文章

    4276

    瀏覽量

    62313
  • 預處理
    +關注

    關注

    0

    文章

    33

    瀏覽量

    10467

原文標題:【SoC】C code如何生成二進制可執(zhí)行文件?實例詳解

文章出處:【微信號:小杜的芯片驗證日記,微信公眾號:小杜的芯片驗證日記】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    不同機器上生成不同的二進制文件

    模型 - 長堆棧(+ modsl0)我們的目標可執(zhí)行文件是* .s19格式。但是,當我們構建我們的軟件時,它會在不同的機器上生成不同的二進制文件!所有設置都相同,并且正在使用相同的工作
    發(fā)表于 11-16 10:27

    一個源文件生成二進制可執(zhí)行文件的步驟

    = var_value3 funcmainvim filename.c=> srcgcc 編譯器filename.c => a.out一個源文件生成
    發(fā)表于 10-27 07:04

    二進制

    二進制   二進制與十進制的區(qū)別在于數(shù)碼的個數(shù)和進位規(guī)律有很大的區(qū)別,顧名思義,二進制的計數(shù)規(guī)律為逢二進一,是以2為基數(shù)的計數(shù)體制。10這
    發(fā)表于 04-06 23:48 ?8155次閱讀
    <b class='flag-5'>二進制</b>

    C語言入門教程-二進制文件

    二進制文件 二進制文件非常類似于結構體數(shù)組,只不過這些結構體被保存在一個磁盤文件而非內(nèi)存數(shù)組中。因為是使用磁盤保存
    發(fā)表于 07-29 14:24 ?1924次閱讀

    二進制編碼和二進制數(shù)據(jù)

    二進制編碼和二進制數(shù)據(jù)   二進制編碼是計算機內(nèi)使用最多的碼制,它只使用兩個基本符號"0"和"1",并且通過由這兩個符號組成的
    發(fā)表于 10-13 16:22 ?4747次閱讀

    二進制電平,什么是二進制電平

    二進制電平,什么是二進制電平 在二進制數(shù)字通信系統(tǒng)中,每個碼元或每個符號只能是“1”和“0”兩個狀態(tài)之一。若將每個碼元可能取的狀態(tài)增
    發(fā)表于 03-17 16:51 ?2341次閱讀

    具有X86到ARM二進制翻譯和執(zhí)行功能的SoC系統(tǒng)設計

      二進制翻譯是一種直接翻譯可執(zhí)行二進制程序的技術,能夠把一種處理器上的二進制程序翻譯到另外一種處理器上執(zhí)行。它使得不同處理器之間的
    發(fā)表于 09-07 10:22 ?2114次閱讀
    具有X86到ARM<b class='flag-5'>二進制</b>翻譯和<b class='flag-5'>執(zhí)行</b>功能的SoC系統(tǒng)設計

    二進制加法程序【C語言版】

    二進制加法程序【C語言版】二進制加法程序【C語言版】二進制
    發(fā)表于 12-29 11:03 ?0次下載

    二進制加法程序【C語言+匯編版】

    二進制加法程序【C語言+匯編版】,多種集合,符合同時愛好C語言+匯編的學習者的胃口。
    發(fā)表于 01-06 11:10 ?0次下載

    C語言教程之十進制轉換為二進制

    C語言教程之十進制轉換為二進制,很好的C語言資料,快來學習吧。
    發(fā)表于 04-22 11:06 ?0次下載

    C語言編程二進制位操作符

    C語言編程二進制位操作符
    發(fā)表于 03-30 14:09 ?6次下載

    Visual-C#數(shù)據(jù)庫存取二進制字段數(shù)據(jù)

    現(xiàn)代的數(shù)據(jù)庫不僅要存放數(shù)值和字符等數(shù)據(jù),還要存放一些二進制類型的文件,常見的如圖片文件、動態(tài)連接庫、可執(zhí)行文件等。對于數(shù)值和字符這些普通數(shù)據(jù)類型,利用上一章中介紹的編輯記錄的方法是完全
    發(fā)表于 04-03 15:12 ?14次下載

    C語言程序內(nèi)存布局該關注哪些內(nèi)容

    C語言代碼(文本文件)形成可執(zhí)行程序(二進制文件),需要經(jīng)過編譯-匯編-連接三個階段。編譯
    發(fā)表于 05-07 08:03 ?916次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>程序內(nèi)存布局該關注哪些內(nèi)容

    C語言程序運行流程包含哪些環(huán)節(jié)

    C語言并不能直接被計算機所理解,需要將C語言轉變成可執(zhí)行代碼,即二進制代碼。在
    發(fā)表于 11-07 15:05 ?1.3w次閱讀

    在Linux上分析二進制文件的10種方法

    這將是你進行二進制分析的起點。我們每天都在與文件打交道,并非所有的文件都是可執(zhí)行類型,除此之外還有各種各樣的文件類型。在你開始之前,你需要了
    的頭像 發(fā)表于 06-18 17:32 ?3106次閱讀