Ch 01 第一個組合語言程式


第一個程式

DOS 的可執行檔包含 COM、EXE 和 BAT 三種檔案。BAT 是批次檔,不在我們討論範圍;COM 檔比較簡單,前幾個程式範例都是 COM 檔;EXE 檔包含表頭,因此比較大載入時也比較慢(可能只慢數個毫秒吧?),較為複雜。雖然 EXE 檔較複雜,但是經組譯、連結後的檔案都會先變成 EXE 檔,還要執行轉換程式( EXE2BIN.EXE )才能轉換成 COM 檔。不過並不是所有的 EXE 檔都可以轉換成 COM 檔。因此現在先來看看 COM 可執行檔吧。

依照不成文的慣例,第一個簡單的程式,似乎都是在螢幕上秀出一段文字,因此我的第一個程式也是如此。底下就是原始檔列表,這程式也是變成 COM 檔後再執行的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
;***************************************
code    SEGMENT                         ;.code 段開始位址
        ASSUME  cs:code,ds:code         ;.假設程式段及資料段
        ORG     100h                    ;.可改成 *.COM 檔
;---------------------------------------
start:  jmp     begin                   ;程式進入點
mes     DB      'Hi, I learn assembly.$';要印出的訊息
begin:  mov     dx,OFFSET mes           ;指向 mes 的位址
        mov     ah,9                    ;呼叫DOS服務程式,AH=9/INT 21H 表示印出字串
        int     21h                     ;呼叫 DOS 服務程式
        mov     ax,4c00h                ;指定要呼叫的服務號碼
        int     21h                     ;呼叫 DOS 服務程式
;---------------------------------------
code    ENDS                            ;code 段結束
;***************************************
        END     start                   ;使組譯器知道程式進入點

組譯、連結、執行

將上述原始碼用任何一個文字編輯器(如筆記本或 UltraEdit 32 或其他文字編輯器)寫好之後,存成純文字檔,假設檔名是 EXAM01.ASM ( 當然你也可以依高興任意取檔名,但連結時要用自己的檔名 )。如果你使用 Win 9x/Me,請開啟『MS-DOS 模式』;如果您使用 XP/Vista/7,請開啟『命令提示字元』,組譯的方法會隨不同版本的組譯器不同,因此選擇適當的方法組譯。雖然是這樣,還是建議讀者依序看看 MASM 5.0 如何組譯,因為這是最原始的方式。另外,假如您已經安裝好虛擬機器,Microsoft Virtual PC 2007 SP1,也已在虛擬機器安裝好了 DOS,那麼可以參閱附錄十一,在虛擬機器中組譯。

用 MASM 5.0 組譯

在 DOS 提示下或命令提示字元堨切換到原始檔所在的子目錄,輸入『..\masm50\masm exam01;』(註一) 組譯原始檔 ( 底下你要輸入的文字用黃色,當然不要忘了輸入完後要按鍵盤上的 Enter 鍵。此外在 DOS 中,大小寫是相同的 ),MASM.EXE 會自動將原始檔名加上 ASM,所以可以不用輸入副檔名。
E:\HomePage\SOURCE>..\masm50\masm exam01; [Enter]

Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.


  51526 + 397850 Bytes symbol space free

        0 Warning Errors
        0 Severe  Errors

此處小木偶的組合語言組譯程式及原始檔不在同一目錄,所以必須指定組譯程式所在目錄,因此前面多了『..\masm50\』,就是告訴 DOS 組譯程式在何處,如果你把原始檔、組譯器、連結器全部都放在一起就不用打這些字了。如果電腦顯示 0 Warning Error 與 0 Severe Error 就是告訴你已組譯完成,接下來你得連結程式庫(*.LIB),輸入『..\masm50\link exam01; (為何要用連結器連結程式庫,請參考第十章)( LINK.EXE 後的;也和MASM.EXE的意義相似,可自己試試 )

E:\HomePage\SOURCE>..\masm50\link exam01; [Enter]

Microsoft (R) Personal Computer Linker  Version 2.40
Copyright (C) Microsoft Corp 1983, 1984, 1985.  All rights reserved.

Warning: no stack segment

最後會出現一個沒有堆疊區段 ( no stack segment ) 的警告訊息,有關堆疊留到第五章再說明,此處我們忽略這項警告訊息。接下來我們將 EXAM01.EXE 檔變成 EXAM01.COM,輸入『..\masm50\exe2bin exam01 exam01.com』

E:\HomePage\SOURCE>..\masm50\exe2bin exam01 exam01.com [Enter]

沒有任何訊息就代表成功了。接下來,對『命令提示字元』輸入『dir』指令,看看我們的檔案有那些?然後輸入『exam01』執行看看:

E:\HomePage\SOURCE>dir [Enter]

 Volume in drive H is DATA_1
 Volume Serial Number is 0330-08F6
 Directory of E:\HomePage\SOURCE

.              <DIR>        02-02-02  21:31 .
..             <DIR>        02-02-02  21:31 ..
EXAM01   ASM           989  03-23-00   6:00 EXAM01.ASM
EXAM01   OBJ           107  02-02-02  22:26 EXAM01.OBJ
EXAM01   EXE           805  02-02-02  22:26 EXAM01.EXE
EXAM01   COM            37  02-02-02  22:27 EXAM01.COM
         5 file(s)          1,938 bytes
         2 dir(s)        7,984.43 MB free

E:\HomePage\SOURCE>exam01 [Enter]
Hi, I learn assembly.
E:\HomePage\SOURCE>

在這個目錄 ( 資料夾 ) 裡,EXAM01.COM 就是我們最後得到的執行檔,當我們在 DOS 提示下或 Windows 的『命令提示字元』下輸入此執行檔檔名就代表我們要執行此程式了。你看,我們的努力終於有了代價,是不是秀出我們所要的文字來。

假如您是在 XP 系統上,那麼執行 exam01.com 時可能無法順利印出這段字來,可能是對 INT 21H 的輸出不太相容,這時你可在虛擬機器下執行看看,請參考附錄十一

上述的過程是 MASM.EXE 是把原始檔 ( 也就是*.ASM ) 組譯為目的檔 *.OBJ,而連結器是把目的檔與程式庫連結起來,變成可執行的檔案 *.EXE,稍後我再作說明。最後可用 EXE2BIN 將 *.EXE 檔轉換成 *.COM 檔。但是並非每次就能寫出正確的程式,所以必須除錯,發現有錯誤時上述步驟就得重複一次,很是麻煩,如果能輸入幾個字來代替就好多了,這就是批次檔的好處,容我稍後解釋如何寫批次檔。現在先看看 MASM 6.11 如何組譯,再來解釋上述原始檔 ( EXAM01.ASM ) 每行的意義。

使用 MASM 6.11 組譯

因為每次寫好原始檔後,都要先組譯再連結程式庫,很是麻煩,所以 MASM 6.0 以後,不再使用 MASM.EXE,而改成 ML.EXE。ML.EXE 能自動呼叫連結器 ( LINK.EXE ) 連結,所以只需下一次命令即可,雖是如此,但是您還得將連結器的位置告訴 ML.EXE 才可以,否則 ML.EXE 會抱怨找不到 LINK.EXE 出現錯誤而停止。我們可以用 DOS 的 PATH 指令告訴 ML.EXE,LINK.EXE 在那一個目錄,如下:

E:\HomePage\SOURCE>path E:\HomePage\masm611d;%path% [Enter]

E:\HomePage\SOURCE>

當我們執行 PATH 指令後,只需執行一次,DOS 就能記住,所以如果原始程式組譯發現錯誤,修改好以後要再組譯時,就不用下 PATH 命令了。只需再輸入『ml /AT 要組譯的檔名』即可。而『%path%』這個參數是指修改 PATH 指令的路徑。詳細情形請看附錄三註五

接下來就執行 ML.EXE。因為小木偶想把原始程式和組譯器分開在不同目錄,所以小木偶就像上一章的安排方式,ML.EXE 在 E:\HomePage\MASM611D 而 EXAM01.ASM 在 E:\HomePage\SOURCE 目錄內,而且小木偶也希望組譯好的程式能放在 E:\HomePage\SOURCE 子目錄內,所以小木偶切換到 E:\HomePage\SOURCE 子目錄內,這樣 DOS 就會在 E:\HomePage\SOURCE 中工作,把組譯好的檔案存放於此子目錄堙C最後下達『ml /AT 要組譯的檔名』指令,這樣 ML.EXE 就能依小木偶的希望執行。『要組譯的檔名』必須是完整的檔名,也就是要包含副檔名,這是 ML.EXE 的語法一定得遵守。最後結果如下:

E:\HomePage\SOURCE>ml /AT exam01.asm [Enter]
Microsoft (R) Macro Assembler Version 6.11d
Copyright (C) Microsoft Corp 1981-1995.  All rights reserved.

 Assembling: exam01.asm

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.

LINK : warning L4017: /r : unrecognized option name; option ignored
Object Modules [.obj]: /r exam01.obj/t
Run File [exam01.com]: "exam01.com"
List File [nul.map]: NUL
Libraries [.lib]:
Definitions File [nul.def]:

至於 ML.EXE 的參數『/AT』是告訴 ML.EXE 我們要製作成 *.COM 檔,ML.EXE 會自動地轉成 EXAM01.COM 而不須再用 EXE2BIN 了。要注意 ML.EXE 的參數是有大小寫的分別,『AT』若變成『at』是會出錯的。

使用 MASM 8.0/9.0 組譯

如果您要使用 MASM 8.0 版或 9.0 版的組義器組譯 exam01.asm,也不是不可以,但是有幾個限制。首先,8.0/9.0 版的 ML.EXE 只能在 Windows 系統中執行,無法在 DOS 作業系統中執行,也不能在虛擬機器的 DOS 堸鶡獢A不過所產生的程式還是能在 DOS 堸鶡獢C第二,8.0/9.0 版的 ML.EXE 本是配合 Visual C++ 組譯 VC 堣煽O的組合語言程式碼,所以預先設定是用來組譯 32 位元的 Windows 程式,如果要組譯 16 位元的 DOS 程式,必須加上『/omf』參數使組譯所得的目的檔格式為 Intel Object Module Format 格式。第三,所使用的連結器,必須是能連結 OMF 格式的目的檔的連結器,最高版本是 5.63 版,不要與連結成 Windows 程式搞混了。底下小木偶假設 8.0 版的 ML.EXE 及 5.63 版的 LINK.EXE 都在『E:\HomePage\MASM8』子目錄堙A而 exam01.asm 在『E:\HomePage\SOURCE』堙G

E:\HomePage\SOURCE>..\masm8\ml /omf /AT exam01.asm [Enter]
Microsoft (R) Macro Assembler Version 8.00.50727.218
Copyright (C) Microsoft Corporation.  All rights reserved.

 Assembling: exam01.asm

E:\HomePage\SOURCE>..\masm8\link exam01 [Enter]

Microsoft (R) Segmented Executable Linker  Version 5.60.339 Dec  5 1994
Copyright (C) Microsoft Corp 1984-1993.  All rights reserved.

Run File [exam01.exe]:
List File [nul.map]:
Libraries [.lib]:
Definitions File [nul.def]:
LINK : warning L4021: no stack segment

E:\HomePage\SOURCE>..\masm8\exe2bin exam01 exam01.com [Enter]

E:\HomePage\SOURCE>

8.0/9.0 版的 ML.EXE 似乎不像 6.x 版的 ML.EXE 能自動執行連結器,因此不得已,只能手動執行。


程式說明

;與 COMMENT

EXAM01.ASM 的第一行是『;***************************************』,凡是在『;』之後的文字都會被組譯器忽略,因此被用來當註解。程式設計師應儘量留下註解,以便日後修改。註解最好說明演算法、所用的原理、變數所代表的意義……,不要寫一些無意義的註解,例如下面的註解是沒有意義的。

;***************************************    ;這是註解

有時註解太長,必須使用好幾行文字時,可以用 COMMENT 來當成註解,COMMENT 的語法是:

COMMENT 分隔號
註解文字
分隔號

分隔號可以是任意字元,但是不可以出現在註解文字中,假如這樣的話,組譯器會認為註解結束了,而發生錯誤。

SEGMENT 與 ENDS 假指令

第二行是 code segment,其中 segment 是組譯器的假指令。所謂假指令是告訴組譯器如何組譯,並不是 CPU 的指令集。組合語言的指令中,有些是指示組譯器如何組譯的,即假指令﹔有些是 80X86 指令,這是使 CPU 真正運算或工作的指令。segment 假指令是告訴組譯器有一個區段 ( segment ) 從這兒開始了。segment 一定會與 ends ( end segment 的簡寫,ends 的 s 是指 segment ) 配對,ends 也是一個假指令,是告訴組譯器,這個區段到此結束了。區段的名稱可任意由英文字母、數字及底線組成,此處我將它取名為『code』區段。真實模式底下,每個區段不可超過 64K 位元組。請參考註二有關假指令的說明。

在組合語言中,每一行程式碼或每一筆資料都必須在某個區段內,否則組譯時組譯器會產生錯誤,更不要說執行了。區段大致可分為程式碼區段、資料區段及堆疊區段,程式碼區段是由許多 80x86 指令組成,這些指令告訴 CPU 該如何動作,該做什麼運算;資料區段是 CPU 動作或運算時所需的資料組成。以加法為例,加表示運算,而被加數與加數表示資料,相加後所得的和也是資料。在能夠由*.EXE 檔轉換成 *.COM 的程式,它的程式段及資料段在同一個段內,換句話說程式段與資料段在 64K 內重疊在一起。

初學者可以將這兩個假指令視為固定格式,就好像 HTML 中的 <HTML></HTML> 一樣。組合語言中,COM 程式的原始檔也有固定格式,就是:

區段名  segment
        assume  cs:code,ds:code
        org     100h
start:
        ;此處放程式內容
區段名  ends
        end     start
當有資料時,可用下面固定格式:
code    segment
        assume  cs:code,ds:code
        org     100h
start:	jmp begin
        ;此處存放資料
begin:
        ;此處放程式內容
code    ends
        end     start

到了 MASM 5.x 以後的組譯器,可以使用較簡單的定義來定義區段。方法是用『.code』定義程式碼區段,用『.data』定義資料區段,一個區段的結束就是另一個區段的開始,如果到原始檔最後,就表示最後一個區段也結束了。例如 COM 程式的原始檔可以寫成:

        .code
        org     100h
start:  jmp     begin
        ;此處存放資料
begin:
        ;此處放程式內容
end     start

ASSUME 假指令

第三行是

assume  cs:code,ds:code

這一行是預先將 CS 和 DS 暫存器設為 code 區段。在 8086 CPU 中共有 4 個 16 位元的區段暫存器,分別是 CS、DS、ES、SS,習慣上分別指向程式碼區段、資料區段、額外區段及堆疊區段。。關於8086暫存器,詳細情形請參考這裡

COM 程式的程式碼、資料段、額外段、堆疊段都在同一區段中,因此此處將 CS、DS 都設為 code 區段。設好之後的用處是,當要存取變數時,就不須再指定 DS 了,否則可能要用凌越區段 ( 參考 24 章 ) 的方法了。

ORG 假指令

第四行中是『org 100h』表示此行以後的程式由 100H ( 加上 H 表示 16 進位 ) 這個位址開始。DOS 由磁碟載入 COM 程式檔案時,會自動把程式碼分配到位址 100H 開始執行,因此必須加入這一行,告訴連結器程式碼要從 100H 開始連結。

什麼是位址呢?電腦所能控制的記憶體很大,當 CPU 要存取記憶體中的資料時,必須要知道得向那一個記憶體要資料才行。而記憶體是有編號的,電腦以一個位元組 ( 位元組是 byte,即 8 位元,位元是 bit ) 為單位做編號,這編號就叫位址。在 DOS 堙A用 XXXX:YYYY 表示位址,其中 XXXX 稱為區段位址 ( segment address ),YYYY 稱為偏移位址 ( offset address ),8086 中每個區段最大可以到 64KBytes ( 64KBytes=65536 個位元組 ) 每一個區段的記憶體的編號是由 0 號到 65535 號,共有 65536 個( 65536 除以 1024 得 64,所以一般都說是 64 KBytes),這 65536 個位址,每一個位址的容量大小只有一個位元組(byte)。就像我們家庭的地址一樣,中華路 263 號,這中華路就像是區段,門牌號碼 263 就像是偏移位址。當 CPU 運算時需要資料,就只要告訴記憶體,要取那一個位址的資料,電腦就會依據哪個區段,哪個偏移位址去存取,就不會弄錯了。

標記:

第六行,start:,是表示一個標記,凡是以『:』結尾的字串都是標記,他表示記憶體中的一個位址,跳躍時會用到,例如 jmp begin,就是表示讓 CPU 跳到 begin: 標記處繼續執行。在跳躍指令後,不需加上帽號,定義標記時才需要用到帽號。 jmp 就是無條件跳躍,就像 BASIC 中的 GOTO 一樣。

DB 或 BYTE 假指令

第七行的指令是 db (define byte),其語法是:

變數名    db     數值
變數名    byte   數值

MASM 6.x 以後才可用 byte 定義位元組,不管是『db』或『byte』,都是一個假指令,它是告訴組譯器這兒有一塊記憶體空間保留起來給前面的變數名使用,而保留的大小是一個位元組 ( 位元組英文是 byte,長 8 個位元 )。一個位元組的大小可以表示 0 到 255 共 256 個數字 ( 28=256),所以如果您的變數數值在此範圍內就可以用 db 來表示。如果要定義兩個位元組可以用

變數名    db     數值1,數值2

假如一開始不知道變數的數值,那麼可用『?』表示:

變數名    db     ?

除了表示變數之外,db 也可以定義的是一個英文句子 ( 術語稱為字串,string ),就像在這個例子堛熔臚C行,但為避免組譯器誤解為數字,所以用『"』或『'』將句子括起來。假如以『db』定義一個字串的話,每一個英文字母會佔用一個位元組,而中文字則佔用兩個位元組。

MOV 指令

MOV 指令的語法是

        MOV     運算元1,運算元2

MOV 在 80X86 組合語言中相當於指定或賦予運算元2的數值給運算元1,類似其他高階語言的『=』之意。例如第 9 行的

mov     ah,9

就是把 AH 設為 9 的意思。也可以把它想成是將後面的資料移動(move)到前面的運算元中。那麼,AH 是什麼呢?AH 是一個 8 位元大小的暫存器。暫存器可以想像成是在 CPU 內部一塊暫時儲存資料的記憶體,這些記憶體大小並不大,每個僅 8、16 或 32 位元長,但是運算速度卻比在記憶體快得多。在 8086/8088 CPU 有 4 個 16 位元通用暫存器,供作加減乘除等運算之用,分別是 AX、BX、CX、DX,而每個通用暫存器,又各分為高位元和低位元的兩個,以 AX 為例又分為 AH、AL,AH 表示較高的 8 位元,AL 表示較低的 8 位元,如下圖所示。

八位元的暫存器,就只能存入 8 個位元的大小,每個位元可能是 0 或一,所以只能表示 28 個數,也就是 0∼255 之間不同的數。16 位元的暫存器,則能表示 216 個數,也就是 0∼65535 之間的數。

MOV 指令的兩個運算元必須長度相同,同樣都為 16 位元或 8 位元,不可以運算元1 為 16 位元,而運算元2 為 8 位元。而且這兩個運算元必須有一個是暫存器或常數數值,不可以兩個運算元同時是記憶體中的資料 ( 亦即變數 )。

OFFSET 假指令

OFFSET 是將其後運算元的偏移位址計算出來。EXAM01.ASM 的第八行是

begin:  mov     dx,offset mes

其意義就是將 mes 所在偏移位址填入到 DX 暫存器中,要注意的是並不是把 mes 的內容存入 DX,而是把偏移位址當成一個數值,存入 DX 堙C如果說偏移位址就是門牌號碼,那麼該偏移位址的內容就是你家堶惟狾磲漱H。每個區段開始的位址都是由 0 開始,而原始程式中每行所佔用的記憶體位元組多寡不盡相同,OFFSET 會去計算每行程式碼所佔位元組數,就可以求出來 mes 所在位址,然後再移到 DX 堙COFFSET 這個指令,是指示組譯器去算出 mes 所在的偏移位址,因此是假指令。

INT 指令

第十行 int 21h,int 表示中斷,在組合語言中,中斷是一門大學問,在此處我們可以把中斷想成是一種副程式,副程式是幫我們執行一些常用的工作,等完成後,再將執行結果傳回給原來程式繼續執行。在一般程式中可能要常常印出一段文字,例如提醒你輸入姓名,或者印出計算的結果,如果每次都寫一段印出字串的程式,不是很沒效率嗎?所以我們常常是把要印出的文字記錄於某處,再傳給一段專門印出文字的程式,這段程式就叫副程式。此處,我們呼叫十六進位的 21 號中斷,此中斷是 DOS 提供的也叫 DOS 服務程式。當我們開機進入 DOS 時,DOS 就會自動的將此中斷也載入記憶體中,組合語言程式常利用 DOS 中斷處理許多繁雜的事,21h 中斷所作的事,都由 AH 內容決定,當 AH=9 進入 21h 中段時表示要印出一段文字,而此文字的起始位址便由 DX 決定,一直印到『$』為止。

DOS 和 BIOS 都提供了許多中斷服務程式,每一個中斷處理的事都不同,因此寫組合語言的人手頭上都應該要有一本中斷列表,以供參考。

第十一行、十二行也是執行 DOS 服務程式,目的是結束程式,在組合語言中結束程式有好幾種方式,最常用的就是 AH=4CH/INT 21H,而 AL 內的數值是表示結束時傳回給 DOS 的錯誤碼,如果你寫過 DOS 的批次檔 ( *.BAT ) 可以利用錯誤碼來選擇。

在此你也可以寫成像下面的樣子,但是要多一個 byte。

        mov     ah,4ch
        mov     al,0
        int     21h
另外在 COM 檔堙A也可以使用 int 20h 來結束程式。

END 假指令

第十六行,end 也是假指令,表示程式結束,end 後面的標記是指程式進入點,但對 COM 檔而言是無意義的,寫不寫都沒關係,因為 COM 檔都是由 100h 開始執行;但對 EXE 檔而言你就可以依需要而加以設定。end 是告訴組譯器,原始碼到此為止了,再下面就沒有了,它並不是告訴 CPU 這個程式結束,因此 end 也是一個假指令。也因為 END 不是告訴 CPU 程式結束了,所以第 11 行到 12 行的『mov ax,4c00h/int 21h』是不能省略,否則會當機。


製作程式的流程

要寫用組合語言寫一個程式,其流程圖大致如下:先用文書編輯軟體寫好原始檔,並存成副檔名為 ASM 的原始檔,然後經組譯器組譯,連結器連結程式庫,再來就是用除錯器除錯了,如果有錯誤,就回到文書編輯軟體修改原始檔,然後再組譯連結除錯,一直重複到沒有錯誤止。整個流程圖如下:

用批次檔組譯、連結

由上圖可知,從撰寫原始檔到除錯,必須在 DOS 模式下輸入指令,當程式較大時並不是一次就能修正所有錯誤,而每次原始檔寫好之後都必須重複一次組譯連結的過程,很麻煩。DOS 的設計者早已想到了這個問題,並且設計好兩種方法解決,第一種是用路徑,第二種是用批次檔 ( 副檔名為 BAT ) 來簡化,此處說明如何使用批次檔,大致有兩個步驟:
  1. 首先要建立一個純文字檔,這個純文字檔可用記事本輸入以下文字,然後存成 CPL.BAT 檔﹔( 檔名可以任意取,但副檔名一定要用 BAT,[Enter] 是表示按 Enter 鍵換行的意思 )
    ..\masm50\masm %1; [Enter]
    ..\masm50\link %1; [Enter]
    ..\masm50\exe2bin %1 %1.com [Enter]
    也可以直接在 DOS 模式產生 CPL.BAT,先切換到原始檔所在目錄,再輸入以下文字:
    E:\HomePage>cd source [Enter]
    
    E:\HomePage\SOURCE>copy con cpl.bat [Enter] →con 表示控制台 ( 控制台包含鍵盤即螢幕 ),
    ..\masm50\masm %1; [Enter]                  →上一行表示由控制台拷貝文字到 CPL.BAT
    ..\masm50\link %1; [Enter]
    ..\exe2bin %1 %1.com [Enter]
    ^Z [Enter](註四)
            1 file(s) copied
    
    E:\HomePage\SOURCE>dir [Enter]
    
     Volume in drive H is DATA_1
     Volume Serial Number is 0330-08F6
     Directory of E:\HomePage\SOURCE
    
    .              <DIR>        02-02-02  21:31 .
    ..             <DIR>        02-02-02  21:31 ..
    EXAM01   ASM         1,121  03-23-00   6:00 EXAM01.ASM
    CPL      BAT            69  02-08-02   1:19 cpl.bat
             2 file(s)          1,190 bytes
             2 dir(s)        7,982.30 MB free

    您可以看出來,其實批次檔的內容,完全照我們所輸入的指令去執行的,其中只有可能會改變的地方用 %1、%2 ……來代替,事實上, %1、%2 ……就好像是『變數』一樣。

  2. 第二,使用這個批次檔時,只需要輸入『cpl 要組譯連結的檔名』即可,請看下面:
    E:\HomePage\SOURCE>cpl exam01 [Enter]
    
    E:\HomePage\SOURCE>..\masm50\masm exam01;
    Microsoft (R) Macro Assembler Version 5.00
    Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.
    
    
      51536 + 418608 Bytes symbol space free
    
          0 Warning Errors
          0 Severe  Errors
    
    E:\HomePage\SOURCE>..\masm50\link exam01;
    
    Microsoft (R) Personal Computer Linker  Version 2.40
    Copyright (C) Microsoft Corp 1983, 1984, 1985.  All rights reserved.
    
    Warning: no stack segment
    
    E:\HomePage\SOURCE>..\masm50\exe2bin exam01 exam01.com
    
    E:\HomePage\SOURCE>
    
    E:\HomePage\SOURCE>dir [Enter]
    
     Volume in drive H is DATA_1
     Volume Serial Number is 0330-08F6
     Directory of E:\HomePage\SOURCE
    
    .              <DIR>        02-02-02  21:31 .
    ..             <DIR>        02-02-02  21:31 ..
    EXAM01   ASM         1,121  03-23-00   6:00 EXAM01.ASM
    CPL      BAT            69  02-08-02   1:19 cpl.bat
    EXAM01   OBJ           107  02-08-02   1:22 EXAM01.OBJ
    EXAM01   EXE           805  02-08-02   1:22 EXAM01.EXE
    EXAM01   COM            37  02-08-02   1:22 EXAM01.COM
             5 file(s)          2,139 bytes
             2 dir(s)        7,982.29 MB free
    
    E:\HomePage\SOURCE>exam01 [Enter]
    Hi, I learn assembly.
    E:\HomePage\SOURCE>
只有黃色的字是我們需要輸入的,本來執行 MASM、LINK、EXE2BIN 這三個程式都必須用鍵盤輸入,但如今都由批次檔的內容代替了。批次檔的內容就好像是我們輸入的字一樣,但是我們只有建立批次檔時輸入一次而已,以後要用時,只需再輸入批次檔名和要組譯連結的原始檔檔名就可以了。

結論


註一:如果在 DOS 模式執行 MASM.EXE 時後面沒有加入組合語言原始檔案名時,MASM.EXE 會詢問你原始檔、目的檔(*.OBJ)、列表檔(*.LST),交互參考檔(*.CRF)的檔名,其中MASM第一個詢問的是原始檔名,這一定要輸入否則會一直問下去。再來就是問目的檔檔名,即使你沒有輸入 MASM.EXE 還是會建立的並且用和原始檔名同樣的名字,只是副檔名不同。而列表檔和交互參考檔可有可無,若直接按下 Enter 鍵,那麼 MASM 就不會建立他們,他們都是純文字檔,可用記事本來觀看,我想你看過之後就應該知道它們是什麼東西,小木偶就不再贅述了。
E:\HomePage\SOURCE>..\masm50\masm [Enter]
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987.  All rights reserved.

Source filename [.ASM]: exam01 [Enter]
Object filename [exam01.OBJ]:[Enter]
Source listing  [NUL.LST]:[Enter]
Cross-reference [NUL.CRF]:[Enter]

  51544 + 418712 Bytes symbol space free

      0 Warning Errors
      0 Severe  Errors
上面的例子就是只有建立目的檔而已。常常為了方便,就輸入『MASM 原始檔名; [Enter]』表示只建立目的檔而已。

如果您只輸入

E:\HomePage\SOURCE>..\masm50\masm exam01 [Enter]

而沒有輸入『;』,那麼 MASM 會詢問您目的檔、列表檔、交互參考檔的檔名。

數年前到現在 ( 民國 98 年,也就是西元 2009 年 ) 許多人都使用 Win XP 作業系統,這時 Windows 系統已使用十幾年了,它有 32 位元和 64 位元版本,且與 DOS 時代 16 位元的可執行檔格式不同,所以產生方法也不相同。

註二:本章所提到的假指令有 SEGMENT、ENDS、ASSUME、ORG、DB 這些指令是告訴組譯器該如何動作,例如區段的開始與結束、留下幾個位元組給某個變數使用等等,這些並不是在執行時候下達給 CPU 的,故稱為假指令。而 JMP、MOV、INT 是真正讓 CPU 有所動作的指令,稱 CPU 指令集。Intel 的 CPU 之所以能相容,有很大的因素就是新的 CPU 的指令集包含了舊的 CPU 的指令集。

註三:100H 的 H 是表示這 100 是十六進位數並非十進位數。如果數目後面沒有任何英文字,就表示此數為十進位,十進位也可以用 D 表示。八進位和二進位數分別用『O』(英文字的 O )和『B』表示。這些英文字都是在數字後面,大小寫皆可。此外十六進位數第一個位數如果是英文字,要在最前面額外加上一個零,否則會被當成變數名或標記名。如果您不熟悉十進位、二進位 和十六進位的話,請立即參考附錄一,在組合語言中常常要用到這幾種進位法。

註四:『^Z』這個字是直接按下 F6 這個鍵,也可以先按住 Ctrl 鍵不放再按下 Z 鍵。

註五:路徑,PATH,是一個 DOS 內部指令,可參考附錄三的說明。其語法是

path 路徑1;路徑2;路徑3......
如果使用者在 DOS 模式下輸入好路徑後,當使用者輸入一個可執行檔,DOS 先在現在的目錄內尋找倘若沒有的話,DOS 會依序到路徑1、路徑2 等路徑去尋找這個可執行檔。

所以如果我們在組譯前下

E:\HomePage\SOURCE>path E:\HomePage\MASM50 [Enter]

這個指令,那麼組譯時,只需輸入

E:\HomePage\SOURCE>masm exam01; [Enter]

就可以了,DOS 會先到 E:\HomePage\SOURCE 這個子目錄去找找看,有沒有 MASM.EXE,如果沒有的話,就會到 path 所指定的目錄去找 MASM.EXE,如果找到的話,就執行它。所以以後就不用再輸入『..\masm50\』,同樣地連結時也不用再輸入『..\masm50\』這幾個字了。

當路徑設立好之後,DOS 會將它存在記憶體的一個地方,因此除非修改或關機,否則 DOS 是不會忘記的。如果我們設好一個路徑,而後又想在路徑上再加上一個子目錄,這時可用『%path%』這個變數,『%path%』代表前次路徑。假如您要 DOS 搜尋兩個以上的子目錄,就用『;』將它隔開。

您也可以在 DOS 提示之下輸入『set』指令,檢查目前已經設好的路徑有那些,但千萬不要輸入『set path=』,如此一來就會把路徑設為空的,亦即清除所有路徑了。


回到首頁到第零章到第二章