hello world的底層原理

hello world是我們學習一門語言的第一個程序佩谣,一直很好奇這個程序底層到底是怎么執(zhí)行起來的呢盖灸?今天就讓我們一探究竟:

#include<stdio.h>
int main()
{
  printf("hellow world \n");
} 

編譯鏈接: gcc hello.c均驶,生成了a.out文件郑口,

 gcc hello.c 
wusong@ubuntu:~/cTest/hellotest$ ls
a.out  hello.c

查看a.out颓影, 使用objdump -h a.out

 objdump -h a.out

a.out:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     0000001c  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000060  00000000004002b8  00000000004002b8  000002b8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       0000003d  0000000000400318  0000000000400318  00000318  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000008  0000000000400356  0000000000400356  00000356  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  0000000000400360  0000000000400360  00000360  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     00000018  0000000000400380  0000000000400380  00000380  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000030  0000000000400398  0000000000400398  00000398  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         0000001a  00000000004003c8  00000000004003c8  000003c8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000030  00000000004003f0  00000000004003f0  000003f0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt.got      00000008  0000000000400420  0000000000400420  00000420  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         00000192  0000000000400430  0000000000400430  00000430  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         00000009  00000000004005c4  00000000004005c4  000005c4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       00000011  00000000004005d0  00000000004005d0  000005d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame_hdr 00000034  00000000004005e4  00000000004005e4  000005e4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     000000f4  0000000000400618  0000000000400618  00000618  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .init_array   00000008  0000000000600e10  0000000000600e10  00000e10  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000008  0000000000600e18  0000000000600e18  00000e18  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000008  0000000000600e20  0000000000600e20  00000e20  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      000001d0  0000000000600e28  0000000000600e28  00000e28  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          00000008  0000000000600ff8  0000000000600ff8  00000ff8  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000028  0000000000601000  0000000000601000  00001000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000010  0000000000601028  0000000000601028  00001028  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          00000008  0000000000601038  0000000000601038  00001038  2**0
                  ALLOC
 26 .comment      00000035  0000000000000000  0000000000000000  00001038  2**0
                  CONTENTS, READONLY

可以看到目標文件格式是分類存儲的各淀,分成了很多段,從左到右诡挂,第一列(Idx Name)是段的名字碎浇,第二列(Size)是大小 ,LMA表示裝載內存地址璃俗,VMA表示虛擬內存地址奴璃,F(xiàn)ile off是文件內的偏移。

基礎知識

從你寫的源代碼到執(zhí)行你的程序城豁,一般經歷了這幾個過程:
源代碼編輯 -> 編譯 -> 鏈接 -> 裝載 -> 執(zhí)行苟穆。編譯,簡單說就是用編譯工具唱星,將你的源碼雳旅,變成可以執(zhí)行的二進制代碼,也叫做目標文件间聊,當然只是對應某一種硬件平臺攒盈,比如此處我用的是Intel的X86系列的CPU,編譯出來的哎榴,就是針對X86的二進制代碼型豁。鏈接就是將多個目標文件合并為一個目標文件,稱作可執(zhí)行文件叹话。 在上面的可執(zhí)行文件中有很多section偷遗,最常見和基礎的段有:

“text”段:代碼段,就是CPU要運行的指令代碼驼壶。

“data”段:數據段氏豌,保存了源代碼中的數據,一般是以初始化的數據热凹。

“bss”段:也是數據段泵喘,存放那些未初始化的數據泪电,因為這些數據還未分配空間,所以單獨存放纪铺。

段一般可以分為loadable和allocatable相速, loadable,可加載鲜锚,就是突诬,原先目標文件里面包含對應的代碼或數據,所以芜繁,裝載器要把這些內容旺隙,load到對應的地址,以便程序可以運行骏令;而allocatable蔬捷,可分配的,最簡單理解就是上面提到的.bss段榔袋,那里記錄了變量名周拐,到時候,你要給這些變量名分配內存空間凰兑。

  • LMA:(Load Memory Address) the address at which the section will be loaded.內存裝載地址表示把程序(經歷過妥粟,由你的源碼,通過編譯器的編譯聪黎,鏈接器的鏈接罕容,形成的那個可執(zhí)行文件,詳細點說就是稿饰,把其中的.text代碼段锦秒,.data數據段等內容)從硬盤裝載到內存的哪個位置。這里問一句喉镰,為什么要搬到內存呢旅择? 程序運行的本質,就是CPU讀取到指令侣姆,然后執(zhí)行生真。這里就涉及到,如果想要你的程序運行捺宗,首先柱蟀,你應該把對應的指令,放到合適的地方蚜厉,CPU 才能讀到长已,才能執(zhí)行。此處合適的地方,有人想到术瓮,直接放到硬盤這里康聂,CPU過來讀取,然后執(zhí)行不就可以了嗎胞四,還不用這么麻煩地將(指令)代碼搬來搬去的恬汁,多省事。但是實際上辜伟,系統(tǒng)就是這么“笨”地搬來搬去氓侧,原因在于,從硬盤上直接讀取指令导狡,速度比直接從內存甘苍,一般PC 上是各種類型的RAM,比如DDR烘豌,此處統(tǒng)稱為Memory/內存,要慢很多倍看彼,所以廊佩,系統(tǒng)才會不嫌棄麻煩,把代碼拷貝到內存里面去靖榕,然后從內存里面讀取指令标锄,然后執(zhí)行,這樣效率會高很多茁计。
  • VMA, (Virtual Memory Address):the address the section will have when the output file is run;那啥是虛擬內存地址呢料皇?簡單說就是,你程序運行時候的所對應的地址星压。此處所謂的虛擬践剂,一般來說,指的是啟用了MMU之后娜膘,才有了虛擬地址和實地址逊脯。此處,我們可以簡單的理解為竣贪,就是內存的實際地址即可军洼。程序運行前,要把程序的內容演怎,拷貝到對應的內存地址處匕争,然后才能運行的。因此爷耀,一句話總結就是:代碼要運行的時候甘桑,此時對應的地址,就是VMA。在多數情況下扇住,LMA和VMA是相等的.LMA和VMA不一樣春缕。而其中最常見的一種情況就是,程序被放到ROM中艘蹋,比如設置為只讀的Nor Flash中锄贼,也就是LMA的地址是Nor Flash的地址,此如隨便舉例為0x10000000女阀,而程序要運行時候的地址是內存地址宅荤,比如0x30000000,也就是VMA 是0x30000000,這時候浸策,就要我們自己保證冯键,在程序運行之前,把自己的程序庸汗,從LMA=0x10000000拷貝到VMA=0x3000000處惫确,然后程序才可以正常運行。有人會問蚯舱,反正對于ROM來說改化,CPU 也是可以直接從ROM里面讀取代碼,然后運行的枉昏。為何還要前面提到的陈肛,弄個LMA 和VMA不同,搬來搬去的呢兄裂?因為ROM句旱,顧名思義,是只讀的晰奖,只能讀取谈撒,不能寫入的。而程序中的代碼段匾南,由于只是被讀取港华,不涉及到修改寫入,是沒有問題的午衰。但是對于數據段和bss位初始化段來說立宜,里面的所有的程序的變量,多數都是在運行的時候臊岸,不僅要讀取橙数,而且要被修改成新的值,然后寫入新的值的帅戒,所以灯帮,如果還是放到ROM里面崖技,就沒法修改寫入了。而且钟哥,另一個原因是迎献,CPU從ROM,比如常見的Nor Flash中讀取代碼的速度腻贰,要遠遠小于從RAM吁恍,比如常見的SDRAM,中讀取的速度播演,所以冀瓦,才會牽扯到將代碼燒寫到ROM里面,然后代碼的最開始写烤,將此部分程序reaload翼闽,重載,也就是從此處的ROM的地址洲炊,即LMA感局,重新拷貝到SDRAM中去,也就是VMA的地方暂衡,然后從那里運行蓝厌。
鏈接器和裝載器的作用
鏈接器
  1. 將LMA寫到(可執(zhí)行的)二進制文件里面去
  2. 解析符號。將不同的符號古徒,根據符號表中的信息,轉換為對應的地址读恃,這里只涉及VMA隧膘,即程序運行時的地址。
Loader寺惫,裝載器
  1. 從二進制文件中讀出對應的段的信息疹吃,比如text,data西雀,bss等段的信息萨驶,將內容拷貝到對應的LMA的地址處。
  2. 如果發(fā)現(xiàn)VMA!=LMA, 即 程序運行時候的地址艇肴,和剛剛把程序內容拷貝到的地址LMA腔呜,兩者不一樣,
    那么就要把對應的內容再悼,此處主要是data核畴,數據段的內容,從剛剛裝載到的位置冲九,LMA處谤草,拷貝到VMA處.這樣,程序運行的時候,才能夠在執(zhí)行的時候丑孩,找到對應的VMA處的變量冀宴,才能找到對應的值,程序才能正常運行温学。

最后再看看.text段到底是存了什么東西呢略贮?objdump -s a.out (-s 表示查看目標文件十六進制格式)

......
Contents of section .fini:
 4005c4 4883ec08 4883c408 c3                 H...H....       
Contents of section .rodata:
 4005d0 01000200 68656c6c 6f20776f 726c6420  ....hello world 
 4005e0 00  
......                  

貌似我們能看懂的也就是rodata只讀數據段中的hello,world枫浙,那我們反匯編看下刨肃,objdump -d a.out , 它輸出文件的匯編形式,下面列出主要的main函數部分箩帚,其實在main函數執(zhí)行前后真友,有很多工作要做,比如初始化函數執(zhí)行環(huán)境等紧帕。

0000000000400526 <main>:
 400526:       55                      push   %rbp
 400527:       48 89 e5                mov    %rsp,%rbp
 40052a:       48 83 ec 10             sub    $0x10,%rsp
 40052e:       c7 45 fc 05 00 00 00    movl   $0x5,-0x4(%rbp)
 400535:       bf d4 05 40 00          mov    $0x4005d4,%edi
 40053a:       e8 c1 fe ff ff          callq  400400 <puts@plt>
 40053f:       b8 00 00 00 00          mov    $0x0,%eax
 400544:       c9                      leaveq
 400545:       c3                      retq
 400546:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 40054d:       00 00 00

左邊是十六進制形式盔然,右邊是匯編形式,至于匯編代碼是嗜,這里不贅述愈案。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鹅搪,隨后出現(xiàn)的幾起案子站绪,更是在濱河造成了極大的恐慌,老刑警劉巖丽柿,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恢准,死亡現(xiàn)場離奇詭異,居然都是意外死亡甫题,警方通過查閱死者的電腦和手機馁筐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坠非,“玉大人敏沉,你說我怎么就攤上這事⊙茁耄” “怎么了盟迟?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潦闲。 經常有香客問我队萤,道長,這世上最難降的妖魔是什么矫钓? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任要尔,我火速辦了婚禮舍杜,結果婚禮上,老公的妹妹穿的比我還像新娘赵辕。我一直安慰自己既绩,他們只是感情好,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布还惠。 她就那樣靜靜地躺著饲握,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蚕键。 梳的紋絲不亂的頭發(fā)上救欧,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音锣光,去河邊找鬼笆怠。 笑死,一個胖子當著我的面吹牛誊爹,可吹牛的內容都是我干的蹬刷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼频丘,長吁一口氣:“原來是場噩夢啊……” “哼办成!你這毒婦竟也來了?” 一聲冷哼從身側響起搂漠,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤迂卢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后桐汤,有當地人在樹林里發(fā)現(xiàn)了一具尸體而克,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年惊科,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亮钦。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡馆截,死狀恐怖,靈堂內的尸體忽然破棺而出蜂莉,到底是詐尸還是另有隱情蜡娶,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布映穗,位于F島的核電站窖张,受9級特大地震影響,放射性物質發(fā)生泄漏蚁滋。R本人自食惡果不足惜宿接,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一赘淮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睦霎,春花似錦梢卸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碑幅,卻和暖如春戴陡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沟涨。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工恤批, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拷窜。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓开皿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親篮昧。 傳聞我的和親對象是個殘疾皇子赋荆,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容