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

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

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

程序從編譯到被執(zhí)行的流程

sakobpqhz6 ? 來源:平凡人筆記 ? 2023-03-15 09:11 ? 次閱讀

當(dāng)掌握越來越多的基礎(chǔ)知識之后,你所看到的代碼視角和你之前看代碼的視角會發(fā)生一個(gè)翻天覆地的變化,就像你寫代碼看到的是一行一行代碼的邏輯,而高級程序員看到的是一行一行指令或者你寫函數(shù)調(diào)用是一個(gè)正常的函數(shù)調(diào)用,其他人看到的是調(diào)用鏈背后被調(diào)用的情況,所以學(xué)東西盡量學(xué)習(xí)一些基礎(chǔ),這樣能夠帶給我們很不一樣的編程體驗(yàn),也能夠讓你了解整個(gè)程序的本質(zhì)。當(dāng)遇到瓶頸之后,更應(yīng)該多學(xué)一些基礎(chǔ)知識來豐富自己的眼界。

首先看下編譯的過程,b6346b74-c2ab-11ed-bfe3-dac502259ad0.png

源代碼會經(jīng)過編譯器,首先編譯成匯編文件,匯編文件經(jīng)過匯編器變成目標(biāo)文件。在目標(biāo)文件當(dāng)中,函數(shù)調(diào)用地址是沒有被真正的鏈接起來的,鏈接的過程是需要經(jīng)過鏈接器,把目標(biāo)文件當(dāng)中相關(guān)的地址信息給鏈接起來,最后形成可執(zhí)行的文件。

c編譯舉例

b6457fcc-c2ab-11ed-bfe3-dac502259ad0.png

這是一個(gè)簡單的add函數(shù),在main方法里面調(diào)用這個(gè)add函數(shù),然后進(jìn)行打印。

生成目標(biāo)文件

gcc -c main.c

b6cfea5e-c2ab-11ed-bfe3-dac502259ad0.png

用gcc -c的命令可以生成一個(gè)目標(biāo)文件,

看下生成的目標(biāo)文件里的地址信息

objdump -d main.o

objdump反編譯看下目標(biāo)文件存了哪些信息,

b7180f6e-c2ab-11ed-bfe3-dac502259ad0.png

b74e6424-c2ab-11ed-bfe3-dac502259ad0.png

這是一個(gè).test段,程序最終在內(nèi)存上面或磁盤上面存儲的時(shí)候,它不是無規(guī)律的存儲,最后被翻譯成機(jī)器碼之后,也是一段一段存儲的,每一段所存的內(nèi)容是不一樣的,像.test段存儲的就是正常的代碼段也是函數(shù)段,而聲明的全局變量會存在.data段或.bss段。

這里只需要理解,我們寫的代碼被翻譯成機(jī)器碼大概的分段邏輯就行了。

左邊是這條指令的地址0 4 5 8 .... ,就是我們寫的程序加載到內(nèi)存當(dāng)中的時(shí)候是被加載成一條一條指令,然后每一個(gè)指令都會對應(yīng)一個(gè)特定的地址,cpu在取的時(shí)候,就會取這個(gè)地址上面的信息,就可以知道這條指令地址所對應(yīng)指令的具體內(nèi)容。目標(biāo)文件的這個(gè)地址是相對地址,相對于當(dāng)前段的地址,當(dāng)前段是.test段,所以是從0開始 按順序排下來。

callq在匯編里面是調(diào)用函數(shù)的指令,這里寫的是33 ,但其實(shí)在真正目標(biāo)文件被鏈接成可執(zhí)行文件之后,33會變成add函數(shù)的絕對地址。

被鏈接成可執(zhí)行文件之后,看下整個(gè)代碼地址的變化,用gcc命令編譯了一個(gè)可執(zhí)行文件,反匯編看下,將.test段的地址列出來了,它已經(jīng)不是相對于.test段的相對地址了,而是一個(gè)絕對地址。

b7deaf70-c2ab-11ed-bfe3-dac502259ad0.pngb879aebc-c2ab-11ed-bfe3-dac502259ad0.png

然后看下調(diào)用callq add函數(shù)的時(shí)候 ,1149所對應(yīng)的首地址是add函數(shù)的第一行。<>括號在真正的機(jī)器代碼中是不存在的,反匯編為了增加可讀性才顯示的。

在看了程序是怎么被編譯成可執(zhí)行文件之后,我們又知道了可執(zhí)行文件里面,每一條指令所對應(yīng)的地址代表什么意思之后,來看下是如何被加載?

這里要明白一點(diǎn),程序是在內(nèi)存里面被執(zhí)行的,被加載到內(nèi)存之后,cpu才能從內(nèi)存里面讀取并執(zhí)行,所以有一個(gè)從磁盤加載到內(nèi)存的過程,這個(gè)過程由加載器去完成的。

提到內(nèi)存的話,就要提到cpu的實(shí)模式和保護(hù)模式。

在很早之前,cpu在實(shí)模式時(shí)期,我們的程序所使用的地址都是物理地址,就是真正的在內(nèi)存芯片上所能看到的物理地址,使用物理地址之后,就會導(dǎo)致我們寫的程序被編譯成可執(zhí)行文件之后,可執(zhí)行文件是由鏈接器編譯成鏈接腳本生成的,然后在鏈接腳本里面可以指定程序的首地址,如果要指定首地址(有一個(gè)默認(rèn)的首地址),在實(shí)模式下,指定了當(dāng)前編譯程序的首地址之后,那它被加載到物理地址之后,這個(gè)首地址就只能是真正的被加載到物理地址的那個(gè)地方,如果它的首地址比如是0x10,那它被加載到的物理地址的首地址如果不是0x10 就會導(dǎo)致后面那些指令的順序出現(xiàn)問題,因?yàn)橹噶钍琼樞蚺挪嫉模蜁?dǎo)致后面的那些指令地址和可執(zhí)行文件里面描述的這些指令地址是不吻合的。

這樣會導(dǎo)致callq函數(shù)會調(diào)用到錯(cuò)誤的地址,所以在cpu的實(shí)模式下,調(diào)用程序,程序在執(zhí)行的時(shí)候,它的首地址要固定住,這樣就會導(dǎo)致一個(gè)問題就是得考慮調(diào)得那個(gè)地址是不是可用的,調(diào)用期間內(nèi)存是不是可用的,所以會演變成后面的cpu保護(hù)模式。

cpu保護(hù)模式能夠讓程序使用的是一個(gè)虛擬地址,現(xiàn)在的64位系統(tǒng)都是使用的頁式管理,基于這個(gè)分析一下。要明白虛擬地址,首先要明白地址空間的概念,地址空間可以理解為進(jìn)程能用的一個(gè)地址范圍,比如進(jìn)程能用的內(nèi)存是512G,然后由于程序經(jīng)過編譯之后是分段的,就認(rèn)為這512G里面,0-10G是屬于.test段,10-20G是屬于.data段,20-200G屬于堆空間,其他范圍分:棧空間是哪個(gè)范圍,內(nèi)核空間又是哪個(gè)范圍,只是將這段區(qū)間劃分為了具體的內(nèi)容所在的這段范圍,但是不會實(shí)際的在內(nèi)存上去分配這些內(nèi)存,只是將范圍劃分出來,而實(shí)際保存的也是這些范圍,當(dāng)需要用到這些范圍地址的時(shí)候,cpu才會去通過MMU列表里面去尋找這個(gè)虛擬地址所對應(yīng)的物理地址,如果沒有這個(gè)映射關(guān)系,才會去真正的分配物理內(nèi)存創(chuàng)建映射關(guān)系,如果可執(zhí)行文件一開始沒有加載到內(nèi)存,那么后續(xù)地址缺失是如何找到磁盤上面的文件位置的?所以需要看下可執(zhí)行文件里面到底有哪些信息?

b8b27fa8-c2ab-11ed-bfe3-dac502259ad0.png

這里列出了可執(zhí)行文件里面段的頭部信息,在段的頭部信息里面包含了虛擬地址、文件的偏移量,文件的偏移量可以理解為磁盤信息,可以通過偏移量去定位到在磁盤上的哪個(gè)位置,所以操作系統(tǒng)是可以這樣做的:在可執(zhí)行文件里面能夠讀到段地址還有文件偏移地址,所以在進(jìn)程被加載執(zhí)行的時(shí)候,剛開始被加載的時(shí)候,是可以為這個(gè)進(jìn)程創(chuàng)建頁表項(xiàng),頁表項(xiàng)是能夠覆蓋每個(gè)段的地址還有文件偏移的地址,但是這個(gè)時(shí)候,只是標(biāo)記這個(gè)頁表項(xiàng)所映射的這個(gè)映射關(guān)系,只是標(biāo)記,并沒有真正的分配實(shí)際的物理內(nèi)存,這樣等到頁缺失的時(shí)候 ,夠找到這個(gè)頁表項(xiàng)并并且能夠從這個(gè)頁表項(xiàng)的標(biāo)記去發(fā)現(xiàn)沒有分配物理內(nèi)存,這個(gè)時(shí)候再從磁盤上去讀,再建立映射關(guān)系,這樣就能夠達(dá)到在真正使用的時(shí)候再去分配物理內(nèi)存的目的了。

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

    關(guān)注

    115

    文章

    3749

    瀏覽量

    80685
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4264

    瀏覽量

    62251
  • 源代碼
    +關(guān)注

    關(guān)注

    96

    文章

    2943

    瀏覽量

    66581
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1608

    瀏覽量

    48986
  • 匯編器
    +關(guān)注

    關(guān)注

    0

    文章

    31

    瀏覽量

    11225
收藏 人收藏

    評論

    相關(guān)推薦

    cc2640 multirole工程代碼沒有被執(zhí)行?

    cc2640 multirole工程代碼沒有被執(zhí)行?在使用cc2640 2.1版本的multirole工程時(shí)出現(xiàn)問題,當(dāng)工程作為主機(jī)連接機(jī)時(shí)會出現(xiàn)一個(gè)問題,當(dāng)機(jī)因?yàn)榫嚯x較遠(yuǎn)等原因與工程主機(jī)斷開
    發(fā)表于 03-14 09:58

    C/C++程序編譯流程

    指令,并生成可重定位目標(biāo)程序的.o文件,該文件為二進(jìn)制文件,字節(jié)編碼是機(jī)器指令。匯編器是將匯編代碼轉(zhuǎn)變成機(jī)器可以執(zhí)行的指令,每一個(gè)匯編語句幾乎都對應(yīng)一條機(jī)器指令。所以匯編器的匯編過程相對于編譯器來講
    發(fā)表于 04-17 16:24

    異常處理程序沒有被執(zhí)行

    Hy-ALL,我的問題是我的異常處理程序沒有被執(zhí)行,而是Stand異常處理程序IS.我定義了我的異常處理程序:代替它,MPLAB提供的一般異常處理
    發(fā)表于 09-17 16:50

    定時(shí)器中斷實(shí)驗(yàn)里的中斷服務(wù)是怎么被執(zhí)行的?

    我試時(shí),一直搞不明白,里面的中斷服務(wù)是怎樣被執(zhí)行的呢?當(dāng)TIM3產(chǎn)生中斷后,Keil 怎么會自動(dòng)執(zhí)行" void TIM3_IRQHandler(void)"這個(gè)服務(wù)程序的呢?是不是函數(shù)名相同就會
    發(fā)表于 09-18 23:21

    源代碼CPU執(zhí)行過程

    1.源代碼CPU執(zhí)行過程.c等高級語言經(jīng)過編譯編譯后轉(zhuǎn)換為.s匯編源代碼經(jīng)過匯編器轉(zhuǎn)化為elf格式二進(jìn)制可
    發(fā)表于 12-20 07:55

    mfc程序執(zhí)行流程小結(jié),MFC程序執(zhí)行順序

     摘要:本文章主要以MFC程序執(zhí)行流程、執(zhí)行順序等執(zhí)行過程的剖析做出的結(jié)論,下面一起來看看原文的具體介紹。
    發(fā)表于 12-08 15:48 ?9469次閱讀
    mfc<b class='flag-5'>程序</b><b class='flag-5'>執(zhí)行</b><b class='flag-5'>流程</b>小結(jié),MFC<b class='flag-5'>程序</b>的<b class='flag-5'>執(zhí)行</b>順序

    C語言程序設(shè)計(jì)實(shí)用教程之如何進(jìn)行順序程序資料和程序概述

    C程序流程一般分為順序結(jié)構(gòu)、選擇結(jié)構(gòu)和循環(huán)結(jié)構(gòu)。 順序結(jié)構(gòu)是程序設(shè)計(jì)語言中最基本的結(jié)構(gòu),順序結(jié)構(gòu)程序由簡單語句組成,語句按書寫順序執(zhí)行,
    發(fā)表于 10-31 18:04 ?1次下載
    C語言<b class='flag-5'>程序</b>設(shè)計(jì)實(shí)用教程之如何進(jìn)行順序<b class='flag-5'>程序</b>資料和<b class='flag-5'>程序</b>概述

    中興通訊表示與中建五局屬于正常商業(yè)糾紛并非失信被執(zhí)行

    就近日媒體報(bào)道中提到的中興通訊被中建五局申請強(qiáng)制執(zhí)行的事宜,記者了解,此事系中興通訊與中建五局的正常商業(yè)糾紛,并非失信被執(zhí)行
    發(fā)表于 12-26 09:13 ?584次閱讀

    時(shí)代芯存共有5項(xiàng)被執(zhí)行人信息,總金額已經(jīng)超過2.45億元

    目前,時(shí)代芯存共有5項(xiàng)被執(zhí)行人信息,總金額已經(jīng)超過2.45億元。知情人士指出,最新的被執(zhí)行人信息或與此前拖欠的工程款有關(guān)。
    的頭像 發(fā)表于 03-05 14:10 ?5405次閱讀

    單片機(jī)C程序編譯、執(zhí)行過程資料下載

    電子發(fā)燒友網(wǎng)為你提供單片機(jī)C程序編譯執(zhí)行過程資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助廣大
    發(fā)表于 04-08 08:42 ?14次下載
    單片機(jī)C<b class='flag-5'>程序</b><b class='flag-5'>編譯</b>、<b class='flag-5'>執(zhí)行</b>過程資料下載

    一條SQL語句是怎么被執(zhí)行

    一直是想知道一條SQL語句是怎么被執(zhí)行的,它執(zhí)行的順序是怎樣的,然后查看總結(jié)各方資料,就有了下面這一篇博文了。 本文將從MySQL總體架構(gòu)---》查詢執(zhí)行流程---》語句
    的頭像 發(fā)表于 09-12 09:44 ?1473次閱讀
    一條SQL語句是怎么<b class='flag-5'>被執(zhí)行</b>的

    羅永浩回應(yīng)被執(zhí)行信息清零

    近日,羅永浩對被執(zhí)行信息清零做出了相關(guān)回應(yīng),稱被執(zhí)行信息清零不等于債務(wù)已經(jīng)全部償還完畢,自己還款遠(yuǎn)超預(yù)期,目前已經(jīng)在按照已達(dá)成的執(zhí)行和解協(xié)議繼續(xù)履行,稱羅老師仍在努力工作。
    的頭像 發(fā)表于 01-06 11:14 ?1584次閱讀

    中斷服務(wù)子程序是如何被執(zhí)行的 ?

    筆者在 《程序是如何在 CPU 中運(yùn)行的(二)》中 PC 指針寄存器的角度分析了一級函數(shù)調(diào)用和二級函數(shù)調(diào)用執(zhí)行的過程,那么中斷服務(wù)子程序...
    發(fā)表于 02-07 11:02 ?2次下載
    中斷服務(wù)子<b class='flag-5'>程序</b>是如何<b class='flag-5'>被執(zhí)行</b>的 ?

    折疊屏手機(jī)鼻祖柔宇科技拖欠百萬合同款成失信被執(zhí)行人,公司累計(jì)被執(zhí)行超 1 億

    廣告公司達(dá)成和解協(xié)議,約定向后者分兩期支付合同欠款 110 余萬元,如未履行任何一期的付款義務(wù),后者有權(quán)立即向法院申請強(qiáng)制執(zhí)行。案件流程顯示,去年 9 月,柔宇科技公司首次被執(zhí)行,執(zhí)行
    的頭像 發(fā)表于 03-01 22:18 ?425次閱讀

    程序編譯被執(zhí)行流程介紹

    當(dāng)掌握越來越多的基礎(chǔ)知識之后,你所看到的代碼視角和你之前看代碼的視角會發(fā)生一個(gè)翻天覆地的變化,就像你寫代碼看到的是一行一行代碼的邏輯
    的頭像 發(fā)表于 03-15 09:11 ?957次閱讀