helloworld經歷了什麼?

《深入理解計算機系統》學習筆記

hello world往往是學習編程時遇到的第一個示例,下面是一個C語言版本:

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}

這個程序會在終端打印hello, world這串字符,那麼這個程序在我們的計算機上到底是怎能被讀取運行的呢?

程序的存儲

我們將這段代碼保存爲文本文件並命名爲hello.c,稱作源程序或源文件。這段代碼裏都是英文字母以及一些符號,然而,計算機內存儲的信息都是二進制的,計算機只能識別由10組成的位(比特)序列,每8個位組成一個字節。那麼英語有26個字母,漢字更是成千上萬個,只用0和1怎麼表示呢?不用怕,我們只要將很多個0與1排列組合一下就能表示很多個了,n位就能表示2n個文字。例如一個字節8位最多就能表示256個。這就是編碼的強大能力了,常見的編碼標準有ASCII和UTF-8。
ascii低128位對照表

程序被翻譯成不同格式

C語言是高級語言,要想在計算機上運行,就必須被翻譯成計算機能理解的機器語言指令。然後這些指令按一種稱爲可執行目標程序的格式打好包,並以二進制磁盤文件的形式存放起來。目標程序也稱可執行目標文件
linux> gcc -o hello hello.c
在Linux上我們用GCC將hello.c翻譯稱可執行文件hello,這個過程可以分爲四個階段。
編譯系統

  • 預處理階段:預處理器cpp根據以井號#開頭的預處理命令修改原始程序。例如這裏hello.c的第一行#include <stdio.h>告訴預處理器讀取頭文件stdio.h的內容(這個文件裏包含了printf這個函數)並把它插入源程序,得到hello.i
  • 編譯階段:編譯器ccl將hello.i翻譯成文本文件hello.s,這裏包含一個彙編語言程序:
main:
  subq    $8, %rsp
  movl    $LC0, %edi
  call    puts
  movl    $0, %eax
  addq    $8, %rsp
  ret
  • 彙編階段:彙編器as將hello.s翻譯成機器語言指令,把這些指令打包成一種叫做可重定位目標程序的格式,並將結果保存到hello.o
  • 鏈接階段:我們在程序裏用到了printf函數,它存在於一個名爲printf.o的預編譯好了的文件中。這個文件需要以某種方式合併到我們的程序中,這就要用到鏈接器ld。結果就得到可執行文件hello。可以被加載到內存由系統執行。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章