在我們要學(xué)習(xí)一門編程語言的時候第一個程序基本上是helloworld,但就是這個簡單的程序到底是如何運行的施禾,在此做一下記錄搁胆。
文章中的部分內(nèi)容來自《深入理解計算機系統(tǒng)》第一章
helloworld 從到創(chuàng)建,執(zhí)行斯碌,輸出簡單消息肛度,再到終止投慈,中間到底是如何運行的伪煤。簡單介紹下。
代碼
#include<stdio.h>
int main(int argc, char const *argv[])
{
printf ("hello world \n");
return 0;
}
二進制文本
- 計算機中职烧,數(shù)據(jù)的存儲我們看到的是一串英文代碼蚀之,其實存儲的是2進制數(shù)據(jù)捷泞,helloworld 程序的代碼可以用 ASCLL碼表示。再把具體的ASCLL碼轉(zhuǎn)為為2進制失受。
-
如圖中的23對應(yīng)的10進制數(shù)據(jù)為35 而35對應(yīng)的為#
程序被其他程序翻譯成不同的格式
hello程序從一個高級的c程序開始因為這樣更容易讓人讀懂拂到。但是如果要運行hello這個程序谆焊,必須要轉(zhuǎn)為編譯成更低的機器語言浦夷。
-
在Linux 中從源程序到目標程序是由編譯器完成的劈狐。
可以用file 命令查看目標程序的詳細信息
可以看出這個程序的格式為elf(對應(yīng)的Windows下的編譯的為pie) 64為程序肥缔,因為處理器是向下兼容的如果要生成32位程序可以使用 (-m32)
在編譯中到底經(jīng)歷了哪些階段
- 預(yù)處理階段(cpp)根據(jù)以#號開頭的命令,修改原始的c程序改艇,比如helloworld 中的第一行 #include<stdio.h>命令告訴預(yù)處理器讀取系統(tǒng)頭文件stdio.h 的內(nèi)容.并把他直接插入程序文本中谒兄,得到一個c程序 ,通常是以 .i 為擴張名。stdio.h 文件在Linux中的(/usr/include目錄下)
- 編譯階段邻耕,匯編器(ccl)為把上面的helloworld.i 反義成hello.s他包含一個匯編語言程序兄世,用(ida查看匯編程序)
- 匯編階段:把源程序的helloworld.s 翻譯成機器語言指令御滩。并將結(jié)果保存在 helloworld.o文件中党远,helloworld.o 是一個2進制文件
- 鏈接階段: 源程序中的hellworld 調(diào)用了printf 函數(shù) 麸锉,他是每一個C 編輯器提供的標準c庫中的一個函數(shù),printf 函數(shù)存在一個名為printf.o的單獨的預(yù)編譯好的目標文中中柳爽,而這個文件必須以某種形式合并到我們helloworld.o程序中鏈接器(ld)就負責(zé)這種合并碱屁。結(jié)果生產(chǎn)一個可執(zhí)行的文件為helloworld娩脾。