第一節 應用工具
一、對程式的認識
寫作程式不難,但要寫出好程式卻不容易。這就好像畫圖一樣,人人都能畫,而畫出來的圖卻可能有天壤之別。
想作一個好畫家,首先要有觀察及分析的能力,面對著雜亂的事物,先整理出頭緒,找到主題。再在畫布上勾出輪廓,這叫做「布局」。布局完畢,根據實際的環境,決定作圖的先後「順序」。順序是一種層次觀念,景物及色彩都有一定的層次,絕不可隨意所之,想到哪裡,畫到哪裡。
觀察考慮完畢,即開始准備,先將畫筆、調色板等工具放妥,把要表現的主要色彩也調好。最後是選擇適當的畫筆,蘸上色彩,按照所觀察的結果,塗在畫布上。
畫圖頗重風格,有些個人主義的藝術家,技巧並不精通,只因為時代潮流或歷史條件,創造了某種獨特的風格,就得以成名享利。一般的畫家則不然,不論是「工筆」抑或「寫意」畫,全靠其技巧及素養,始能求生存。至於藝術大師,則首重風格,再加上素養、技巧,方可揚名立萬,永垂不朽。
最糟糕的畫匠,既沒有觀察能力,更談不上技巧和風格,除了照著別人的作品抄襲、模仿外,創造不出有價值的作品。若程式師也如此,只能照著別人的意思,填填指令,不過是個程式匠罷了。
在觀察分析之下,把欲表現的內容整理成為具體的步驟,用電腦術語來說,是為「程式分析」,相當於畫畫中的「布局」。再下去,便是「流程」制作,或是作畫的順序。將各種程式的層次安排妥當,才能開始寫作程式,相當於開始作畫。
這些觀念牽涉甚廣,不是三言兩語可以說完。本書僅以組合語言寫作的訓練為目的。如果讀者能善用組合語言的各種技巧,又能充份認識所要完成的工作,至少可以滿足「工筆畫」的條件。對一個電腦程式而言,目前畫「工筆畫」的價值要比「寫意」為高。
下面,我們要以工筆畫的立場,來理解組合語言的應用。對油畫或水彩畫而言,色料相當於程式用的「資料」,調色盤就是運用資料的「暫存器」,畫筆等於「指令」,一切都准備妥當,所謂「作畫」就是「寫程式」。
程式是由一系列的定義和指令組織成的可執行的程序,需由一種檔案的形式(.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
這種用法,完全是給匯編程式「看」的,程式本身並沒有增加任何指令。
其他規定,請參閱各相關手冊。
二、對資料的認識
在畫布上,所有色彩都是由紅、藍、黃三原色及白色調制而成,瞭解色彩的變化是畫家的基本素養。在電腦中,所有的資料則都由二進位數據組成,要寫程式,必須對二進位的特性先有深刻的認識。
絕大部份的程式師,都不知道二進位數據的妙用,充其量能夠很快地換算二進位與十進位的數值。再不然,由二進位值領會到圖形的點陣排列,如此而已。
應該注意的一點,是電腦的基本單位在於八個開關,不用足就是浪費。如果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。