深入理解計算機系統 1

第一章 計算機系統漫遊

1.1 信息就是 位+上下文

hello程序的生命週期就是從一個源程序(源文件)開始的,即程序員利用編輯器創建並保存的文本文件,文件名是hello.c .源程序實際是一個由值10組成的位(bit)序列,八個位被組成一組,稱爲字節.每個字節表示程序中某個文本字符.

大部分的現代系統都是用ASCII標準來表示文本字符,這種方法實際上是用一個唯一的單字節大小的整數值來表示每個字符.

hello.c程序以字節序列的方式存儲在文件中,每個字節都有一個整數值,而該整數值對應於某個字符.注意,每個文本行都是以一個不可見的換行符‘\n'來結束的.呀對應的整數值是10.這樣子由ascii字符構成的文件稱爲文本文件,所有其他文本文件都稱爲二進制文件.

hello.c的表示方法說明了一個基本道理:系統中的所有的信息,包括磁盤文件,存儲器中的程序,存儲器存放的用戶數據以及網絡上面傳送的數據,都是由一串位表示的.區分不同數據的唯一方法就是我們讀到這些數據對象時的上下文.比如 在不同的上下文,一個同樣的字節序列可能表示一個整數,浮點數,等等.

作爲程序員,我們需要了解數字的機器表示方式,因爲他們與實際的整數和實數是不同的,他們是對真值的無限近似值,有時候會有意想不到的行爲表現.這方面基本原理在第二章詳細論述.

旁註,c語言的起源

貝兒實驗室研究的,有什麼特點呢

unix操作系統息息相關,

小而簡單

是爲實踐目的設計的.

 

1.2 程序被其他程序翻譯成不同的格式

hello 程序的生命週期是從一個高級c語言程序開始的.因爲這種形式能夠被人讀懂,然而,爲了在系統上運行hello.c程序,每條c語句都必須被其他程序轉化成一系列的低級程序語言指令.然後這些指令按照一種稱爲可執行目標程序的格式打好包,並以二進制磁盤文件的形式存儲起來,目標程序也可稱爲可執行目標文件.

unix系統上,從源文件到目標文件的轉化是由編譯器驅動程序完成的:

unix>gcc-o hello hello.c

在這裏 gcc編譯器驅動程序讀取源程序文件hello.c,並把它翻譯成一個可執行目標文件hello .

這個翻譯的過程可分爲四個階段完成,執行這四個階段的程序(預處理器,編譯器,彙編器,和鏈接 器)一起構成了編譯系統.

預處理階段  預處理器(cpp)根據以字符#開頭的命令,修改原始的c程序.比如hello.c第一行的#include <stdio.h >命令告訴預處理器讀取系統頭文件stdio.h的內容,並把它直接插入程序文本中,結果就得到另外一個c程序,通常是以.i作爲文件擴展名.

編譯階段,編譯器(ccl )將文本文件hello.c 翻譯成文本文件hello.s,它包含了一個彙編語言程序.彙編語言程序的每句語句都以一種標準的文本格式確切的描述了一條低級機器語言指令.彙編語言是非常有趣的,因爲他爲不同的高級語言的不同編譯器提供了通用的輸出語言,例如c編譯器和fortran編譯器產生的輸出文件用的是一樣的彙編語言.

彙編階段, 接下來,彙編器(as )將hello.s翻譯成機器語言指令,把這些指令打包成一種叫做 可重定位目標程序的格式,並將結果保存在目標文件hello.o.

hello.o是一個二進制文件,它的字節編碼是機器語言指令而不是字符.如果我們在文本編輯器中打開hello.o文件,看到的將是一堆亂碼.

鏈接階段,請注意,hello程序調用printf函數,他是每個c編譯器都會提供的標準c庫的一個函數.printf函數存在一個名爲printf.o的單獨的編譯好的目標文件中,而這個文件必須以某種方式合併到我們的hello.o程序中,鏈接器(ld)就負責處理這種合併,結果就得到hello文件,他是一個可執行目標企鵝文件 ,(或者簡稱爲可執行文件),可以被加載到內存中,由系統執行.

旁註 GNU項目

gccgnu(gun's  not  unix )的縮寫,是發起的一個免費的慈善項目(cs大法好,這種開源精神啊啊啊啊啊 ,一生推,)

1.3 瞭解編譯器如何工作是大有益處的

對於像hello.c這樣簡單的程序,我們可以依靠編譯系統生成正確有效的機器代碼.但是 有一些主要的願原因促使程序員必須知道編譯器是如何工作的 其原因如下

優化程序性能 現代編譯器都是成熟工具 通常可以生成很好的代碼  作爲程序員 我們無需爲了寫出高質量的代碼而去了解編譯器的內部工作  但是 爲了在c 程序中做出好的編碼選擇 我們確實需要了解一些機器代碼以及編譯器將不同的c語句轉化成機器代碼的方式 .例如 一個switch語句是否比一系列的if then else語句高效的多

在第三章 我們將介紹兩種相關的機器語言 IA32 X86-64.會介紹編譯器如何把不同的c語言結構轉化成他們的機器語言的   第五章 學習如何通過簡單轉換c語言代碼 以幫助編譯器更好的完成工作  從而調整c程序的性能. 第六章  學習存儲器的層次結構特性 c語言編譯器將數組存放在編譯器的方式 以及c程序是如何能夠利用這些知識從而更高效的運行

鏈接時出現的錯誤  根據我們的經驗 一些最令人困擾的程序往往都與連接器操作有關.尤其當你準備構建大型的軟件系統時  .例如 連接器 報告它無法解析一個引用 這是什麼意思?在第七章  會得到解答

避免安全漏洞 多年來 緩衝區溢出

是造成大多數網絡和Internet服務器安全問題的主要原因.存在這些錯誤是因爲很少有人能理解限制他們從不收信任的站點接受數據的質量和格式的重要性.學習安全編程的第一步就是理解數據和控制信息存儲在程序棧上的方式引起的後果 作爲學習彙編語言的一部分 將在第三章描述棧原理和緩衝區溢出錯誤.還將學習程序員 編譯器 和操作系統可以用來降低攻擊威脅的方法

1.4  處理器讀並理解存儲在存儲器中的指令

此刻 hello.c源程序已經被編譯器系統翻譯成可執行文件hello  並存放在磁盤上面.

要想在unix系統運行該可執行文件  我們將它的文件名輸入到稱爲外殼的應用程序中

Unix>./hello

helloworld

Unix>

外殼是一個命令行解釋器 它輸出一個提示符 等待你輸出一個命令行 然後執行這個命令.

如果該命令行的第一個單詞不是一個內置的外殼命令  那麼外殼就會假設這是一個可執行文件的名字   它將加載並運行這個文件   所以在此列中  外殼將加載並運行 hello程序 然後等待程序終止       hello程序在屏幕上輸出他的信息 然後終止    外殼隨後輸出一個提示符 等待下一個輸入的命令行   

1.4.1  系統的硬件組成

爲了理解hello程序運行時  發生了什麼  我們需要理解一個典型系統的硬件組織    

總線

貫穿整個系統的是一組電子管道 稱作總線  它攜帶信息字節並負責在各個部件間傳遞   通常總線被設計成傳遞定長的字節快 也就是字  字中的字節數(即字長)就是一個基本的系統參數 在各個系統中的情況都不盡相同    現在大多數機器字長有的是4個字節 有的是8個字節   爲了討論方便 假設字節爲四個字節 並且總線每次只能傳送一個字

IO設備

這是系統與外部世界的聯繫通道   我們的事例系統包括

發佈了30 篇原創文章 · 獲贊 1 · 訪問量 4760
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章