c語言程式的執行過程(以輸出hello,world為例)
1.c原始檔的儲存
任何資料在計算機中都以二進位制的樣式進行儲存,即0和1兩種儲存表示,那麼c原始檔中的各種字元要想儲存在計算機中作為可執行的指令,那麼必須得以二進位制0或1的形式儲存在其中,因此,需要將c原始檔的需要被以某種方式“翻譯”成二進位制儲存進計算機。
資料型別表示數字的型別如int,double 等型別在記憶體中是以換算的二進位制存的,而字元型別等在記憶體中是以ASCII存的,這個通過查ASCII得到相應的二進位制,然後存放於記憶體。
比如:32767 當作int型 為整數,利用除2取餘法得到相應的二進位制數存於記憶體(本來應該存補碼,但是正數的補碼和原碼相同)所佔的記憶體空間跟其對應的資料型別有關,可能還與機器有關,
而32767 當作字元 即“32767”,這時應該分解‘3’,‘2’,‘7’,‘6’,‘7’,然後查對應的ASCII碼 對應的值為:0011001 00110010 00110111 00110110 00110111 所以在存放的即為該二進位制的組合,且佔5個位元組的記憶體
將指定的字元“翻譯”成對應二進位制檔案需要“統一”的“密碼本”,使得在任何一臺計算上c原始檔都以相同的二進位制形式儲存。而翻譯這個c原始檔的“密碼本”就是ASCII碼。
ASCII使用8位二進位制數表示256個字元,這些字元包括32個大小寫字元,10個數字,以及其他的字元,例如,一個輸出“hello,world”的ASCII為
#include <stdio.h>
int main(void)
{
printf("hello,world\n");
return 0;
}
即符號#的ASCII碼為35,i的ASCII為105......
而ASCII中35的二進位制為0010 0011,i為0110 1001......
因此c原始檔在計算機中儲存為0010 0011 0110 1001 ......
2.c原始檔的編譯
Linux系統上的編譯hello.c:
c原始檔僅僅是以二進位制的形式儲存在計算機中,而我們要實現的是計算機輸出“hello,world”,那麼需要將這些二進位制檔案編譯成計算機可以識別的指令,“告訴”計算機我們要輸出“hello world”。
構成這些計算機可以識別的二進位制指令稱為機器語言,因此,c語言的編譯就是編譯成機器語言共計算機執行。
在Linux系統中,將c原始檔編譯成可執行的二進位制指令檔案是由gcc編譯器完成的,gcc是gnu組織的開發的程式語言編譯器。
輸出“hello,world”的hello.c的編譯流程:
編譯一個hello.c的程式總共分為四個階段:預處理,編譯,彙編和連結
預處理階段:預處理階段是根據程式中字元#開頭的命令並執行相關操作,在holle.c中#開頭的第一行為#include <stdio.h>,前處理器就讀取c庫中的stdio.h的內容將其插入到hello.c文字中生成一個新的檔案hello.i;
編譯階段:編譯器ccl將hello.i翻譯彙編程式儲存在檔案hello.s中,其中的main作為一個函式給出了機器語言的輸出指令;
.file "hello.c"
.section .rodata
.LC0:
.string "hello,world"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
彙編階段:彙編器將hello.s中的組合語言翻譯成計算機可以識別的機器語言存為hello.o二進位制檔案;
連結階段:在c原始檔中我們引用了printf列印函式,而計算機要識別這個函式也要由二進位制指令組成。而在頭部檔案中stdio.h作為c語言的標準庫,其中已經定義了printf的介面,系統根據介面去讀取已經寫好的printf.o二進位制指令檔案,將其與hello.o檔案合併為hello二進位制檔案,稱為可執行目標檔案或可執行檔案。
3.hello檔案的執行過程
Linux上執行hello列印輸出:
開啟shell從鍵盤輸入./hello,shell會優先把輸入的字串當做內建命令,若不是則會將其當做可執行檔案的名字處理。shell將計算機I/o介面連線的輸入裝置輸入的字串通過匯流排介面存入暫存器,再存入記憶體中。
從鍵盤中讀取shell命令流程:
完成./hello輸入後,當從鍵盤上輸入回車後,shell得知命令輸入完成,開始執行一系列指令從磁碟複製hell檔案到記憶體中,流程如下:
當hello檔案被複制到主存之後,處理器開始執行hello程式的main程式的指令。流程是將這些指令從主存複製到暫存器,再從暫存器複製到顯示裝置上,最終顯示到螢幕上,流程如下圖:
相關文章
- 入門輸出Hello World!——C語言C語言
- 【c語言】期望輸出str = hello world 的兩種方法C語言
- C語言列印“Hello World“C語言
- 輸出hello world
- 程式語言執行過程
- 幾乎所有程式語言的hello, world程式(1)
- 幾乎所有程式語言的hello, world程式(2)
- 幾乎所有程式語言的hello, world程式(3)
- 各類程式語言的Hello World寫法
- python輸出hello worldPython
- 用19種程式語言寫Hello World
- C語言的編譯連結執行過程C語言編譯
- 【開發語言】PHP、Java、C語言的編譯執行過程PHPJavaC語言編譯
- 使用Xcode實現第一個C語言程式——Hello worldXCodeC語言
- 第一個shell程式設計,輸出hello world!程式設計
- R語言入門之Hello worldR語言
- Ruby語言入門之Hello world
- hello world"你知多少------300種程式語言中的"hello world"程式匯
- c 語言輸出1000以內的逆序數
- Java實現第一個程式碼,輸出 hello worldJava
- C語言輸入輸出C語言
- Linux C++ 開發3 - 你寫的Hello world經過哪些過程才被計算機理解和執行?LinuxC++計算機
- C語言系列之 跨平臺的 Hello, world 與 system -尹成-專題視訊課程C語言
- JVM中的Hello World是如何執行的?JVM
- docker學習1|使用docker輸出hello worldDocker
- 以圖靈機為師:透過微調訓練讓大語言模型懂執行計算過程圖靈模型
- 《快學 Go 語言》第 1 課 —— Hello WorldGo
- Docker第一彈:下載執行hello-world程式Docker
- POSIX執行緒程式設計起步(1)-Hello World (轉)執行緒程式設計
- 程式語言的演化過程
- Android hello world例項Android
- 01-C++ "hello world"C++
- C# Hello,World(1)
- 程式設計中的遞迴(C語言為例)程式設計遞迴C語言
- 使用Golang語言編寫Hello World Web應用GolangWeb
- C語言程式設計之《資料輸出》C語言程式設計
- 2022-07-26:以下go語言程式碼輸出什麼?A:5;B:hello;C:編譯錯誤;D:執行錯誤Go編譯
- ABAP程式Hello World