程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編語言的藝術-基本認識(一)

匯編語言的藝術-基本認識(一)

編輯:匯編語言

第一節 應用工具

一、對程式的認識

寫作程式不難,但要寫出好程式卻不容易。這就好像畫圖一樣,人人都能畫,而畫出來的圖卻可能有天壤之別。
想作一個好畫家,首先要有觀察及分析的能力,面對著雜亂的事物,先整理出頭緒,找到主題。再在畫布上勾出輪廓,這叫做「布局」。布局完畢,根據實際的環境,決定作圖的先後「順序」。順序是一種層次觀念,景物及色彩都有一定的層次,絕不可隨意所之,想到哪裡,畫到哪裡。
觀察考慮完畢,即開始准備,先將畫筆、調色板等工具放妥,把要表現的主要色彩也調好。最後是選擇適當的畫筆,蘸上色彩,按照所觀察的結果,塗在畫布上。
畫圖頗重風格,有些個人主義的藝術家,技巧並不精通,只因為時代潮流或歷史條件,創造了某種獨特的風格,就得以成名享利。一般的畫家則不然,不論是「工筆」抑或「寫意」畫,全靠其技巧及素養,始能求生存。至於藝術大師,則首重風格,再加上素養、技巧,方可揚名立萬,永垂不朽。
最糟糕的畫匠,既沒有觀察能力,更談不上技巧和風格,除了照著別人的作品抄襲、模仿外,創造不出有價值的作品。若程式師也如此,只能照著別人的意思,填填指令,不過是個程式匠罷了。
在觀察分析之下,把欲表現的內容整理成為具體的步驟,用電腦術語來說,是為「程式分析」,相當於畫畫中的「布局」。再下去,便是「流程」制作,或是作畫的順序。將各種程式的層次安排妥當,才能開始寫作程式,相當於開始作畫。
這些觀念牽涉甚廣,不是三言兩語可以說完。本書僅以組合語言寫作的訓練為目的。如果讀者能善用組合語言的各種技巧,又能充份認識所要完成的工作,至少可以滿足「工筆畫」的條件。對一個電腦程式而言,目前畫「工筆畫」的價值要比「寫意」為高。
下面,我們要以工筆畫的立場,來理解組合語言的應用。對油畫或水彩畫而言,色料相當於程式用的「資料」,調色盤就是運用資料的「暫存器」,畫筆等於「指令」,一切都准備妥當,所謂「作畫」就是「寫程式」。
程式是由一系列的定義和指令組織成的可執行的程序,需由一種檔案的形式(.asm)經過編譯程式 (masm.exe) 的處理,將原始檔轉變為目的檔(.obj),然後再將一個或數個目的檔經過聯結(link.exe)成為執行檔(.exe),或者再用 exe2bin. exe 制成記憶限在64kb以下的命令檔(.com)。
程式師應熟悉上述過程中的每一細節,方能順利完成程式寫作。
程式的寫作方式本無定則,完全看需求及應用而定。可是正如一幅畫,在布局時,程式師應該先有全部的觀念,然後逐步實行。為了提高效率,這些步驟,有必要加以歸類。結果就是所謂的模組。
模組的良窳,決定了程式寫作、修改及再應用的效能。在寫作時要求理念一貫,連續進行。修改應方便靈活,不致錯誤叢生。而應用上功能要完整,可以獨立調用。 
根據上述條件,程式的結構大致上可分為:
1,主程式:連貫性的處理過程,應該一次考慮清楚,細節暫 時放在一邊,先把大架構寫出來,以免顧首不顧尾。在空間足夠的情形下,大架構應該是一個完整的模組,且在整體的觀念下,統一處理。
這種做法,對程式偵錯及修改有很大的幫助。因為修改和調整最多、對功能影響最大的,必然是主程式。若主程式都在同一模組中,比較容易得到理想的效果。

2,副程式:副程式都是一些細節的處理,可以用‘CALL’的方式執行。原則上說來,細節的處理經常重覆發生在不同 的情況下,作為副程式相當有利。只是應該注意調用的手 續,為了效率,通常將需要處理的參數或資料,經由暫存器或者必要時用緩沖器載入。
既然是數個程式均可共用的副程式,而且此類程式為一獨立的過程,所以應該事先分別測試,保證無誤。
此外,各副程式的入口處,宜明白的交待暫存器的使用方式,且要能一目瞭然。

3,子程式:子程式與副程式有一點不同,就是具備完整的機能。所謂完整的機能,指該段程式可以獨立執行、有固定的功能。在應用時,兩者沒有分別,然而在寫作時,子程式的考慮要慎重些。

4,資料檔:資料檔也可以視為一種靜態的程式,雖然不是執行用的,但卻是執行時不可或缺的素材。資料檔的設計應該注意空間的利用,等長度的資料結構最具效率,最好保證資料起點為雙數,以節省16位元匯流排的執行速度。
在應用緩沖器時,切忌隨意設置,往往程式師們設了一緩沖器,等後來發現沒有必要,再想刪掉就麻煩大了。所以事先應安排妥當,以便於隨時查找和調整。安排的方式視使用的情形而定,有的以模組歸類;也可以用字母排序為依據;再不然就加上詳細注釋說明功能及使用的程式標號。

5,應用表:在本書第四章第六節將介紹應用表的功能和應用方式,此類表一次設計完成以後,很少需要再修改,為了工作效率,獨立成為一個檔案,自有其必要性。

此外,各種程式的命名最好能有代表性,以便於應用;程式不能太大,否則編輯耗時費事;分檔時,則要注意標號宣告及各段安排的問題。在磁盤中,應該專辟一個子目錄,不要把各種不相干的程式,都混合在一起。
第二章三、四節中已規定了格式的標准,此處僅再補充一點。即各緩沖器的定義與使用時的長度應相等,否則在編譯或聯結時,容易發生錯誤。聯結時,有時並無足夠的錯誤訊息,供程式師得知錯誤產生的原委。最難理解的錯誤,往往與緩沖器的定義有關,即定義的類型與使用的類型不一致。另外一個情況是段值的改變,其補救方法為在應用時,臨時加一「前置定義」。
所謂「前置定義」是指當暫存器為一字元時,其前應加寫BYTE PTR,否則用 WORD PTR 以確定其值,即可保證安全。
如:MOV BYTE PTR BBSDOT1,AL
此外,每當段值有所改變時,都加寫一條:
ASSUME CS:XXX,DS:YYY,ES:ZZZ 
這種用法,完全是給匯編程式「看」的,程式本身並沒有增加任何指令。
其他規定,請參閱各相關手冊。

二、對資料的認識

在畫布上,所有色彩都是由紅、藍、黃三原色及白色調制而成,瞭解色彩的變化是畫家的基本素養。在電腦中,所有的資料則都由二進位數據組成,要寫程式,必須對二進位的特性先有深刻的認識。
絕大部份的程式師,都不知道二進位數據的妙用,充其量能夠很快地換算二進位與十進位的數值。再不然,由二進位值領會到圖形的點陣排列,如此而已。


二進位就是開關的觀念,把一連串的開關聯在一起,其所能發生的作用,完全在於每一個開關、以及各開關組合應用的功能。
說得明確一點,先要將各種需要設計的功能分析清楚,找出其共通的因素,如果這些因素能用「開」及「關」兩個簡單的狀態代表,則可以用二進位制加以控制。在理論上,一開一關只有兩種作用,而兩組開關就有222 種作用,最理想的設計 是將開關的排列組合數用到極限。
舉例而言,電腦上應用的彩色,就是最理想的設計之一。在電腦中,最基本的應用單位為「字元」(Byte),每一字元有8個「位元」(Bit),相當於8個「開關」。為了要最精簡地應用多種彩色,只以三原色與輝度組合,八個開關就能產生 256種不同的彩色。茲將各開關所代表的彩色分列如下:
開關一 (bit 1):正藍色
開關二 (bit 2):正綠色
開關三 (bit 3):正紅色
開關四 (bit 4):灰色 (高輝度)
開關五 (bit 5):黑色 (低輝度)
開關六 (bit 6):淺藍色
開關七 (bit 7):淺紅色
開關八 (bit 8):淺青色
★上述 (bit n) 是從 n=1 開始計算。

應該注意的一點,是電腦的基本單位在於八個開關,不用足就是浪費。如果8個不夠,再增加便有16個。所以,因事制宜,在設計的時候,唯有用8的倍數才劃算。
但是,宇宙中的事物,不見得剛好是八的倍數。如果設計的人沒有這種認識,不能把所處理的資料,以8為限制條件去劃分,就無法利用這種有利的條件,當然,也就得不到最理想的結果。
所以,要想程式具有最高的效率,首先要把資料整理成為八的倍數值結構。把資料整理為最有效的結構方式,稱為「資料結構」,關於這一點,在後面將有較詳細的例證。
每個字元有 256種排列組合,即相當於 256個十進位的數字。為了方便人的理解,通常將字元寫成十六進位形式,並在其數字後加一‘H’,以別於十進位數字。
茲將十進制與十六進制對應表列於下面:
二進位值 八進位值 十進位值 十六進位值
0 0 0 0H
1 1 1 1H
*10 2 2 2H
11 3 3 3H
*100 4 4 4H
101 5 5 5H
110 6 6 6H
111 7 7 7H
*1000 *10 8 8H
1001 11 9 9H
1010 12 *10 0AH
1011 13 11 0BH
1100 14 12 0CH
1101 15 13 0DH
1110 16 14 0EH
1111 17 15 0FH
*10000 *20 16 *10H
★ 凡前有 *者表示進位。
★★二進位數後應加‘B’,八進位後應加‘O’。
由上可知,十六進制仍沿用十進位數字,只是到了10時,已無現成數字可用,只好借用英文字母。在程式中,匯編程式為了分辨ASCII 字符與十六進制數值,通常規定凡十六進位數值以英文字母開始者,在其字母前加一‘0’。

三、對暫存器的認識

暫存器 (Register) 相當於調色皿,資料相當於色料。把色料放進調色皿裡,為的是要得到預定的效果,暫存器對於資料亦然。
調色皿有大有小,深度有深有淺,其目的是針對不同的情況,以作有效的處理。暫存器也是一樣,應用得好,程式會很精簡,容易修改、閱讀。否則,想到哪一個就用哪一個,沒有原則,沒有章法,這種程式委實不敢恭維。
暫存器的重要性,在於處理方便靈活、速度快,占用空間小。不幸8088 CPU的暫存器很少,用起來總是捉襟見肘,辛苦異常。正因為此,暫存器的善用與否,成為程式效能高低的關鍵技術。
有些程式師不願意精打細算,經常設定一些「緩沖器」,利用緩沖器可以任意定名、便於記憶的優點,竟把珍貴的暫存器,當作各緩沖器間、搬運資料的交通工具,只見資料不停的搬進搬出。雖然程式師省了點事,但運行速度白白浪費了,空間也被糟蹋了。寫這樣的組合程式,遠不如去用高階語言。
當然,緩沖器是有必要的,但也只限於「必要」的情況,而且,在程式規劃時,就要考慮各種應用的條件,把緩沖器內的值取出後,一次處理完畢。如果不能一次解決或是經常要用到的資料,則設法放在暫存器中。
實際上,任何程式不可能在一個過程中,同時需要很多特殊的資料。好的程式師能把復雜的工作處理得有條不紊,功力不夠的,往往把簡單的事情弄得令人難以理解。8088的暫存器的確是不夠用,但是卻不至於少到要以緩沖器取代的地步。
工作的好壞、成敗,與人的組織能力有絕對的關系,限於篇幅,我們不能多談。可是,利用暫存器的特性,來處理繁雜的資料,倒也是訓練組織力的方法之一。
首先,我們應該把暫存器視為工具,瞭解工具的功能、性質,然後要能銘記於心,純熟地加以運用。
根據個人的理解,暫存器概分六類:
1,分段用
程式段 CODE SEGMENT :CS
資料段 DATA SEGMENT :DS
堆棧段 STACK SEGMENT :SS
特設段 EXTRA SEGMENT :ES
2,堆棧用:
堆棧值 STACK POINTER :SP
棧用器 BASE POINTER :BP
3,記憶轉換用:
源存器 SOURCE INDEX :SI
終存器 DESTINATION INDEX :DI
4,一般用:
累積器 ACCUMULATOR :AX
兼用器 BASE :BX
計數器 COUNTER :CX
資料器 DATA :DX
5,標志用:旗號值 STATUS :FLAG
6,指示用:執行值 INSTRUCTION POINTER :IP
為了便於記憶,我們給暫存器定中文名,其定義為:
凡分段用者率稱「段」,做為各段起始位置指示用,其計值方式為:系統中的絕對地址=(本值×16)+各段定址值
如:資料段為 1600H,乘16即為16000H。


如源存器為 1234H,則此源存器在系統中由0算起的地址為:17234H。
應注意者,各種以「器」定名的暫存器,皆有限用的段,切勿混用。
凡定名為「值」者,皆為不能用來供程式寫作的暫存器。如堆棧值(SP)系指示堆棧所在位置;旗號值(FLAG)表示旗號標志的情況;執行值(IP)則代表程式當前所執行的地址。這些暫存器值並非不能改變,但對技巧尚不夠純熟者,最好保持原值,不要妄動。
經常使用的「器」有兩種,一以16位元為單位,如棧用器、源存器及終存器; 另一種則具有兩個分別稱「高位」及「低位」、各有8位元,可單獨使用,也可合並為16位元的暫存器AX,BX,CX,DX。
暫存器通常作為容器用,但有些多用為記憶區之定址,以便將其中貯存的資料取出應用。前者稱為容器功能,可以作計算、邏輯處理等。後者稱為定址功能,系供處理各「器」所定位址的資料用。由於8088 CPU的定址方式,受限於當初不成熟的設計理念,偏偏 IBM獨具慧眼,選中了它,所謂城門失火,殃及池魚,讀者不得不多花點功夫,小心應付。
棧用器(BP)屬於堆棧段的記憶位置,系提供給高階語言結構使用,對組合語言來說,功能不大,但若善於運用,也不無價值。
源存器(SI)固定指向資料段,將源存器中的資料取出,所指的是取出資料段中的資料。設若
DS=2000H SI=1234H,則
SI中的1234H 系指系統中 2000H×16加上位址值 1234H。
不過,使用者不必去計算,只要知道是由資料段起,位址為1234H 即可。
終存器(DI)較為復雜,通常它是指向資料段,可是有幾個指令涉及大量資料轉移,需要由源存器搬到終存器。由於受限於分段的設計,為了便於段間應用,所以特別規定:在這種情況下終存器系指向特設段(ES)。也就是說,只能由資料段移向特設段。程式師可以先設定各段的段暫存器,再作轉移。若要在同一段中作資料轉移,則應使資料段=特設段。
一般用的暫存器,都可以分成兩個8位元、各命名為高、低位暫存器,如:
累積器:AX 高位 AH ,低位 AL
兼用器:BX 高位 BH ,低位 BL
計數器:CX 高位 CH ,低位 CL
資料器:DX 高位 DH ,低位 DL
其中累積器的功能最強,可以做乘、除計算,AH尚有貯存旗號的特殊指令。尤其是從記憶區中取值或將值放進記憶區內時,效率最高,如 LODS , STOSW等。
由於其功能高,運用靈活,所以宜於打雜,千萬不要賦與固定的使命。
兼用器則有一種重要的特性,它是一般用暫存器中,唯一能自記憶區中讀取資料者(XLAT指令除外),所以作為「資料及定址轉換」 (後文將專門介紹此一功能) 方便異常。
計數器常用作「回路」或次數的記錄,也有專用的指令,除非不得已,或者計數用得不多,最好保留備用。
資料器功能最少,最好固定其用途,選擇經常需要應用的資料,置放其中,以便發揮時間空間的最高效率。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved