想像一下,假設你要「舉起你的手臂」,你要對你的手臂說什麼話?

「啥都不說!」我想幾乎每個人都會這樣想。

「要說些什麼呢?我要他動他就動了。」這是很合理的想法。事實上,以我貧弱的「生理與醫學」知識,也不知道你得說什麼手臂才會聽你的話動起來。

但是,理論上,你的手「動與不動」之間,應該是有差異的。當你起心動念,要把手舉起來的時候,大腦必然是送出了訊號才讓手臂舉起來。如果你的手腳不聽使喚,肯定會是一件麻煩事。

再想像一下,假設有顆球向著你的臉飛過來,你會怎麼做?

你可能「想都不想」就把手舉起來,潛意識就想要擋住球,以免它砸到你的臉。

因此,我們大概可以簡單的認為,無論是大腦還是中樞神經,都會發送某種訊號,讓你的手腳活動。只是那訊號是什麼樣的形式?沒有人知道。

組合語言的的功用就很像控制手腳的訊號一樣,神秘而難解。當然,控制手腳的神經訊號可能要更加難解億萬倍,所以科幻影集中的劇情,「在癱瘓的人身上植入晶片,設法重建神經的聯繫並控制肢體」似乎還沒有實現。但是,組合語言(相較之下)簡單多了。
我們只要學習組合語言,就可以操作處理器,讓電腦做運算。

但在進行組合語言的學習之前,要再次強調:我們學習的目的,在於大致了解處理器的運作原理,而不是成為「程式設計師」。要成為程式設計師得努力學習程式語言的種種,這不是本欄的目的。

8086處理器系統簡介
8086處理器系統的大致結構如下:
● 指令集(Instruction Set)
請回想之前學過的內容,如果處理器只能做加法,它的用途肯定不大。所以經過長時間的演進,8086除了會做加法,也會做減法、乘法和除法及各種邏輯運算。把這些演算的方法「格式化」變成一個個的「指令」,讓想要使用處理器的人可以「下指令讓處理器做事」。比方說,以前教過的「ADD AX, BX」,這ADD就是加法的指令。

請到Wikipedia查詢「x86 instruction listings」這個條目,可以大致先了解8086有哪些指令可供運用。我的建議是:學到再說,先不用緊張。

●暫存器(Register)
之前已經介紹過,8086有14個暫存器,名稱分別是AX、BX、CX、DX、SP、BP、SI、DI、IP、CS、DS、ES、SS和FLAG。請特別注意:其中AX、BX、CX和DX這四個暫存器,每個都可以再分成兩半運用。以AX而言,還可以分為AH(高的8個bit)和AL(低的8個bit),依此類推。不過,我覺得暫存器的概念比名稱更該牢記。

所謂暫存器,是因為處理器乃是「電子式」的設計,我們使用電子開關作為各種運算的「閘」,而這暫存器就像是小小的資料暫存空間,只是透過工程師的巧思設計,資料會用「電位高低的形式」暫存在裡面──並且可以在這裡進行各種運算(「運算」才是重點)。

就拿「ADD AX, BX」這段指令碼而言,處理器會把AX的值和BX的值相加之後,放到AX裡面。暫存器的最大功用,就是能在裡面(你也「只能」在這裡面)做各種運算。所以寫組合語言程式的人,整天都在和暫存器搏鬥。

你也可以說,所有的應用程式說穿了都只是暫存器的控制。在某一本教科書上的說法,甚至認為暫存器的控制技巧就控制了電腦工業的未來。

在硬體設計上,暫存器的運作是由「控制」、「算術與邏輯運算」之類的單元來進行的。不過,當你寫程式時你就會忘了這些單元了,你只能不斷的思考要怎樣有效的利用暫存器進行各種有用的運算。

● 記憶體
但對於程式設計師而言,一個程式無非是資料的運算與搬移。

請再看一遍,「一個程式無非是資料的運算與搬移」,記住了嗎?

程式存放在記憶體中,指令碼和資料不斷從記憶體中饋入處理器/暫存器裡面,經過運算再寫回記憶體中。所以如何有效的進行記憶體資料的搬移,也是程式設計(與處理器硬體設計)的重點。

● I/O系統(輸入/輸出系統)
運算的結果是各種文字/數字資料,得印出來給人看才行。此外,資料得從記憶體饋入/寫回記憶體中,這都需要經過所謂的「I/O系統」。

現代的個人電腦,I/O系統是由所謂的「核心晶片組」構成。透過這I/O系統核心晶片組,處理器可以連接各種儲存媒體和週邊裝置(硬碟、光碟、顯示裝置、鍵盤、滑鼠、印表機……)。

先抓個模擬器:emu8086
了解了硬體架構之後,該是讓它做些事情動起來的時候了!上「生物」課的時候,可憐的青蛙總得犧牲而讓學生們解剖,作為了解生物結構的「活教材」。幸好,我們學習處理器不用解剖它,我們用「模擬器」就好。再次強調,使用8086來學習,正是因為它「夠單純」。所以,請到「www.emu8086.com」這個網站,抓一個「emu8086」的程式。這程式是個Shareware,定價為19.95美金,各位可以試用看看。底下的教學,我們就用它來示範(它比Debug要親和一點,呵呵)。

好,假設我們要印「一個字」,要怎麼做?

這牽涉到三個概念:「DOS的中斷向量表」、「ASCII表」和「8086組合語言程式架構」。

● DOS中斷向量表
所謂的「中斷向量」,是早期的作業系統提供的所謂「系統服務」。目前我們先說明所謂的「DOS系統服務」。

總之,DOS提供了一系列的系統服務,稱之為「INT 21h」。

比方說,你要印字,你就得先知道,只要使用編號2號的系統呼叫即可。而程式碼大概是這樣的:


MOV  AH, 02h  ;把AH暫存器放入數字2(2h後面的h指16進位)
MOV DL, ‘A’  ;把DL放入要印的字,這裡我們要印出A
INT 21h  ;執行21h中斷


這三行碼可以印出一個A字,而每一個系統服務,都有和它編號對應相關的規定,這編號大多得先移到暫存器AH裡面。比方說,編號9號的DOS中斷可以提供「印字串」的服務,但是你得在AH放入9,DS:DX裡面放入「指向字串的記憶體位址,字串的結尾得放一個$符號」,而每一個熟練的DOS程式設計師都像一個「活生生的對照表」。

● ASCII表
ASCII大概可以稱之為「美國國家標準交換碼」,是英語世界主要使用的一種文字交換碼。

對於初學者而言,要大概注意的是:其實處理器最重要的功能是數字的運算,文字反而是依據使用者的需求,由作業系統定義的,和處理器關係不大。比方說,印字的服務,其實是DOS的開發公司(Microsoft),依據他們自己認定的方法來做支援。所以,早期的DOS不支援中文,就讓中文電腦的應用很晚才起步,一直到Windows 95支援多國語系才比較流行。但是對處理器而言,中文、英文的最底層都只是數字而已,作業系統的開發公司會善用處理器的能力,設法做出各國語文的支援。一般而言,在處理器的學習時,都只會用到英文和數字。

ASCII就只是一個「數字」和「文字」的對應表,就像是10進位數字65就代表「A」這個字,10進位數字111則代表小寫的「o」。一般在組合語言程式中,習慣用單引號把文字括號起來。所以,「MOV DL, 65」、「MOV DL, ‘A’」和「MOV DL, 41h」這三行指令碼都是一樣的意思(當你寫「65」時表示這是10進位數字,當你寫「41h」時表示這是16進位數字)。因為,處理器基本上只懂數字,(它只根據電子訊號的電位高低做動作)。所以為了寫程式者的方便,你可以用各種習慣的方式來表示文數字──只要你自己知道你在做什麼就好。

● 8086組合語言架構
組合語言程式最簡單的架構就是:程式開始(入口)、程式本體(執行)、程式結束(離開)。通常,程式本體就由各種指令碼和系統呼叫所組成(看你的程式目的而定)。複雜一點的組合語言程式,還會包含堆疊空間和資料空間。未來我們會寫稍微複雜一點的程式,多寫過之後,你就漸漸了解「組合語言是怎麼一回事」,也會漸漸知道「8086是怎麼一回事」了。

本期結語:最後我們來簡單的印個A
請參考「印出A程式」的圖片,輸入一個「印出A」的小程式。如果你輸入正確,你放進DL的值就會被印出(按下emulate按鈕)。



這個模擬器的好玩之處就在於,你可以一步一步的看著程式執行的狀況,請使用「Shift + F8」來進行程式的單步追蹤(如果你只用F8,程式會跑到INT 21h裡面,你會追到不知道哪裡去,所以建議用Shift + F8會比較好),你也可以觀察組譯出來的指令碼,或是觀察暫存器裡面的數值變化。下一期,我們可以用這模擬器寫更複雜的程式,更進一步觀察8086的工作狀況。

熱門新聞

Advertisement