彙編語言(1)——從機器到彙編

《彙編語言(王爽 著)》讀書筆記

1. 彙編語言的出現

  最早期出現的計算機,是名副其實的“計算”機。這個機器可以執行一系列特定的指令,即機器指令。而由機器指令構成的集合被稱爲指令集,也就是我們說的機器語言。機器指令是由一系列的二進制數字0和1構成的。計算機將這些二進制的數字轉變爲一系列的高低電平,驅動計算機內的各種電子器件,進行運算。

  其實嚴格來說,讀取指令並且執行計算和控制功能的,只是計算機裏面的一個模塊,叫做CPU(Central Processing Unit)。計算機發展到現在,CPU已經被集成到一塊芯片當中了,被稱爲微處理器(microprocessor)。每一種微處理器,由於其硬件設計和內部構造的不同,就需要不同的電平脈衝來控制它工作。所以每一種微處理器也都有自己的機器指令集,即機器語言。

  早期的程序設計均使用機器語言,但是這種即難辨識又難以記憶的機器語言給行業發展帶來了障礙。彙編語言應運而生。

  彙編語言實際上就是用簡短的英文縮寫來表示機器語言中的相應指令。由彙編器鏈接器處理後,彙編語言就被翻譯爲機器語言,可由機器來執行。雖然只做了簡單的抽象,這已經大大提高了程序的可讀性。編語言由三種指令構成:

彙編指令:機器碼的助記符
僞指令:如assume cs:code,由編譯器執行
其他符號:如+、-、*、/,由編譯器識別

其中只有彙編指令有對應的機器碼,構成了彙編語言的核心。

2. 計算機結構和原理的再認識

  大多數計算機採用了馮·諾伊曼體系結構,由輸入設備,輸出設備,主存儲器和中央單元構成,如圖1.1。


IAS計算機結構

圖1.1 ISA計算機的結構

  IAS是馮·諾伊曼設計的首臺應用了儲存程序思想(stored-program concept)的計算機,並且成爲了通用型計算機的鼻祖。所謂的儲存程序思想就是將指令和數據一同儲存在儲存器中,計算機自己從儲存器中讀取指令並執行,程序就能夠通過修改存儲器中的值來得到改變。這一想法由馮·諾伊曼和艾倫·圖靈在幾乎同一時期產生,最終由馮·諾伊曼爲建造EDVAC (Electronic Discrete Variable Computer)首次公開提出。在馮氏結構中,CPU能也只能從主存儲器(main memory,也即內存)中讀取指令。

從機器指令的角度來看,一個計算機程序實際做的事情就是不停的操縱存儲器和CPU內部的寄存器,控制二進制數據的流動。

要理解這句話,我們先看一下CPU是如何控制計算機的各個部件的。

  內存全稱爲內部存儲器(internal memory),儲存着指令和數據,沒有內存的CPU就如同沒有記憶的大腦一樣,是根本無法工作的。一般來講,存儲器被劃分若干個,存儲單元從0開始依次編號,每個存儲單元可以存儲1個字節(byte),即8個比特(bit)。我們之前提到的指令和數據,在存儲時是沒有任何區別的。引用王爽在《彙編語言》中的形象的類比:“就像圍棋中的棋子,在棋盒裏的時候沒有任何區別”。關鍵在於CPU對於他們的解釋,這是後話。

  CPU在操縱內存中的數據時,需要指明三點:操縱何處的數據,做何種操作,需要的附加數據(如,執行寫入時的寫入數據)。實際上,除了內存以外,CPU還需要和很多種存儲器進行交互,它們(包括內存)可以分爲兩種:ROM(Read Only Memory)和RAM(Random Access Memory)。CPU在與它們交互時,均涉及到下面三類數據的交互:

地址信息:存儲單元的地址
控制信息:器件的選擇,讀或寫的命令
數據信息:讀或寫的數據

這些信息的交互是通過三組導線傳遞的,如圖1.2。


CPU從內存中讀取數據

圖1.2 CPU從內存中讀取數據的過程

這些導線被稱爲總線,連接着CPU以及其他芯片。總線從物理上看就是一根根導線的集合,從邏輯上分爲三類,地址總線,控制總線和數據總線。

  計算機有很多外部設備,直接控制這些外設的是插在主板的擴展插槽上的接口卡。CPU通過總線與接口卡相連,向接口卡發送命令進而控制外設。接口卡上也帶有裝有BIOS的ROM,某些需要暫存數據的接口卡上也有自己的RAM存儲器。CPU操縱接口卡的方式就是操縱裏面的存儲器。實際上,CPU在讀寫這些存儲器時,通過控制總線發出的都是內存的讀寫命令。也就是說,CPU在操縱它們的時候,把它們總的看作一個由若干個存儲單元組成的邏輯存儲器,這個邏輯存儲器被稱爲內存地址空間。另一種對內存地址空間的定義是根據地址總線的尋址範圍得來的。在彙編語言中,我們面對的就是內存地址空間。


將各類存儲器看作一個總的邏輯存儲器

圖1.3 將各類存儲器看作一個總的邏輯存儲器

  在特定物理存儲器的地址空間中讀寫數據,實際上就是在相對應的物理存儲器中讀寫數據。CPU就這樣控制了各種接口卡,從而控制了各種外部設備。舉個例子,在8086PC的內存空間中,顯存對應的地址空間爲B8000H~BFFFFH的32KB的空間,在這個地址空間寫入數據,寫入的內容被解釋後會立即顯示在顯示器上。

  從最底層來看,CPU的確是在控制各種二進制數據的流動。

3. CPU的內部

  從宏觀認識了整個計算機的構造和原理後,現在來看看CPU。一個典型的CPU主要由運算器寄存器控制器內部總線構成。但在彙編語言中我們關心的只是其中的“存儲器”——寄存器(register)。不同CPU寄存器的個數和結構是不同的,以下全部以Intel 8086CPU(以下簡稱8086CPU)爲例展開討論。


8086CPU的寄存器

圖1.4 8086CPU的寄存器

  8086CPU共有14個寄存器,且均爲16位。其名稱和主要功能如圖1.4所示。由於8086CPU的上一代CPU中的寄存器都是8位的,爲了保證兼容,8086CPU的AX,BX,CX和DX這四個寄存器都可以分爲兩個獨立的8位寄存器來使用,分別爲AH,AL,BH,BL,CH,CL,DH,DL。所以8086CPU可以一次性處理兩種尺寸的數據:字節(byte,由8個bit組成)和(word,由2個byte構成)。這樣看來,二進制數據在計算機中至少是以8個爲一個基本單元出現的。爲了在表示上更加直觀,我們經常使用16進制,並且在16進制數據後面加H,在二進制數據後面加B以區別。

  當使用彙編語言編程時,我們使用匯編指令不斷地在與和存儲器和寄存器打交道。因爲寄存器的數目有限,用法也有要求,所以我們不僅要明確各個寄存器的使用方法,還需要對任何時候各個寄存器的狀態瞭然於胸。這樣在編程時顯得十分的麻煩,這時候,高級的語言的優勢就體現出來了,高級語言通過編譯器來管理寄存器的使用,從而使程序員從中脫身,能專注於業務邏輯的實現。而且彙編程序中的確有一些語句是機械性的重複。但是編譯器也有效率不高甚至出bug的時候,這時候憑藉彙編知識,我們就能自己做一些優化。而且通過彙編語言來了解計算機的構造和運行原理也是不錯的切入點。竊以爲對於“學習XXX還有沒有必要”這種問題的正確解答可能比學習本身還要困難:P。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章