《微機原理與接口技術》課件第4章_第1頁
《微機原理與接口技術》課件第4章_第2頁
《微機原理與接口技術》課件第4章_第3頁
《微機原理與接口技術》課件第4章_第4頁
《微機原理與接口技術》課件第4章_第5頁
已閱讀5頁,還剩204頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第4章

匯編語言程序設計4.1匯編語言程序格式4.2偽指令4.3匯編語言源程序結構4.4匯編語言程序的上機過程4.5匯編語言程序設計4.6程序設計舉例習題4

4.1

匯編語言程序格式

4.1.1匯編語言的程序結構

1)?指令語句

指令語句是功能性語句,由Intel8086/8088CPU提供的指令形成,實現(xiàn)一定的操作功能,能夠被編譯成機器代碼。

2)?偽指令語句

偽指令語句也叫指示性語句,只是為匯編程序在翻譯匯編語言源程序時提供有關信息,并不產生機器代碼。

程序中的語句:

BUF1DB34H

BUF2DB2AH

SUMDB ?

就是偽指令語句,其功能是在內存中開辟3個名字分別為BUF1、BUF2、SUM的字節(jié)存儲單元,前兩個單元的初值分別為34H和2AH,SUM僅指定一個字節(jié)的空單元,并不定義確定的初值。

實際上,匯編語言源程序中還可出現(xiàn)宏指令語句或系統(tǒng)調用。宏指令語句就是由若干條指令語句形成的語句體,編譯時被展開。一條宏指令語句的功能相當于若干條指令語句的功能。系統(tǒng)調用是直接調用操作系統(tǒng)提供的專用子程序。

4.1.2匯編語言的語句格式

指令語句和偽指令語句的格式是類似的,格式如下:

[名字]指令助記符,操作數(shù)[;注釋]

其中,帶方括號的項可以省略,注釋內容以分號(;)引導。

1.名字

1)名字的標識符

名字也就是由用戶按一定規(guī)則定義的標識符,可由下列符號組成:

(1)英文字母(A~Z,a~z);

(2)數(shù)字(0~9);

(3)特殊符號(?、@、_等)。

2)名字的定義規(guī)則

(1)數(shù)字不能作為名字的第一個符號;

(2)單獨的問號(

??)不能作為名字;

(3)一個名字的最大有效長度為31,超過31的部分計算機不再識別;

(4)匯編語言中有特定含義的保留字,如操作碼、寄存器名等,不能作為名字使用。

為了便于記憶,名字應該做到見名知意,如用BUFFER表示緩沖區(qū),用SUM表示累加和等。

3)名字的兩種主要形式

名字有標號和變量兩種主要形式。

(1)標號。標號在代碼段中定義,后面跟著冒號“:”,它也可以用LABEL或EQU偽操作來定義。此外,它還可以作為子程序名定義,由于子程序由偽指令定義,因此子程序名不需冒號說明。標號經常在轉移指令或CALL指令的操作數(shù)字段出現(xiàn),用以表示轉向地址。

標號有三種屬性:段基值、段內偏移量(或相對地址)和類型屬性。

段基值(SEG)屬性:是標號所在邏輯段的段基值,即段起始地址的前16位。此值必須在一個段寄存器中,而標號的段則總是在CS寄存器中。

段內偏移量(OFFSET)屬性:是標號距離段起始地址的字節(jié)數(shù),對于16位段是16位無符號數(shù),對于32位段則是32位無符號數(shù)。

類型(TYPE)屬性:類型表示該標號所代表的指令的轉移范圍,分為NEAR和FAR兩種。如果為NEAR型,則標號只能在段內引用;如果為FAR型,則標號可以在段間引用。

(2)變量。變量在數(shù)據(jù)段、附加數(shù)據(jù)段或堆棧段中定義,后面不跟冒號。它也可以用LABEL或EQU偽操作來定義。變量經常在操作數(shù)字段出現(xiàn)。它也有段、偏移及類型三種屬性。

段屬性:定義變量的段起始地址,此值必須在一個段寄存器中。

偏移屬性:變量的偏移地址是從段的起始地址到定義變量的位置之間的字節(jié)數(shù)。對于16位段,是16位無符號數(shù);對于32位段,則是32位無符號數(shù)。在當前段內給出變量的偏移值等于當前地址計數(shù)器的值,當前地址計數(shù)器的值可以用$來表示。

類型屬性:變量的類型屬性定義該變量所保留的字節(jié)數(shù),如BYTE(DB,1個字節(jié)長)、WORD(DW,2個字節(jié)長)、DWORD(DD,4個字節(jié)長)、FWORD(DF,6個字節(jié)長)、QWORD(DQ,8個字節(jié)長)、TBYTE(DT,10個字節(jié)長)。

在同一個程序中,同樣的標號或變量的定義只允許出現(xiàn)一次,否則匯編程序會指示出錯。

2.指令助記符

指令助記符用來指明不同的操作指令,如MOV、ADD等都是指令助記符。

3.操作數(shù)

指令中的操作數(shù)是指令執(zhí)行的對象。對于一般指令,可以有一個或兩個操作數(shù),也可以沒有操作數(shù);對于偽指令和宏指令,可以有多個操作數(shù)。當操作數(shù)多于一個時,操作數(shù)之間用逗號分開。操作數(shù)可以是常數(shù)或表達式。

1)常數(shù)

(1)數(shù)值常數(shù)。匯編語言中的數(shù)值常數(shù)可以是二進制、八進制、十進制或十六進制數(shù),書寫時用加后綴(如B、O或Q、D、H)的方式標明即可。對于十進制數(shù),可以省掉后綴。對于十六進制數(shù),當以A~F開頭時,前面要加數(shù)字0,以避免和名字混淆,如十六進制數(shù)A6H,應該寫成0A6H,否則容易和名字A6H相混。

(2)字符串常數(shù)。包含在單引號中的若干個字符即形成字符串常數(shù)。字符串在計算機中存儲的是相應字符的ASCII碼,如‘A’的值是41H,‘AB’的值是4142H等。

(3)符號常數(shù)。用符號名來代替的常數(shù)就是符號常數(shù),如COUNTEQU3或COUNT=3定義后COUNT就是一個符號常數(shù),與數(shù)值常數(shù)3等價。

2)表達式

由運算對象和運算符組成的合法式子就是表達式。表達式分為數(shù)值表達式、關系表達式、邏輯表達式和地址表達式等。

(1)算術運算符。算術運算符有:+

(加)、-

(減)、*?(乘)、/?(除)、MOD?(取余除)。

算術運算符可以用于數(shù)值表達式和地址表達式中,用于計算數(shù)據(jù)或地址的結果。下面的兩條指令是正確的:

MOV

AL,4*8+5 ;數(shù)值表達式

MOV

SI,OFFSET

BUF+12 ;地址表達式

(2)邏輯運算符。邏輯運算符有:AND(與)、OR(或)、XOR(異或)、NOT(非)。

邏輯運算符只能用于數(shù)值表達式中,不能用于地址表達式中,其運算結果為“真”或“假”。邏輯運算符和邏輯運算指令是有區(qū)別的。邏輯運算符的功能在匯編階段完成,邏輯運算指令的功能在程序執(zhí)行階段完成。

在匯編階段,指令AND AL,78HAND0FH等價于指令AND

AL,08H。

(3)關系運算符。關系運算符有:EQ(相等)、LT(小于)、LE(小于等于)、GT(大于)、GE(大于等于)、NE(不等于)。

關系運算符要有兩個運算對象。兩個運算對象要么都是數(shù)值,要么都是同一個段內的地址,其運算結果為“真”或“假”。結果為真時,表示為0FFFFH;運算結果為假時,表示為0000H。

指令MOVBX,32EQ45等價于MOVBX,0。

指令MOVBX,56GT30等價于MOVBX,0FFFFH。

4.注釋

注釋是語句的說明部分,用來說明一條指令或一段程序的功能,由分號(;)開始,適當?shù)丶有┳⑨寖热?,可以增加程序的可讀性,便于閱讀、理解和修改程序。匯編源程序時,注釋部分不產生機器代碼。

一條語句可以寫在多行上,續(xù)行符使用&。

4.1.3匯編語言的運算符

1.分析運算符

分析運算符的運算對象是存儲器操作數(shù),即由變量名或標號形成的地址表達式,運算結果是一個數(shù)值。運算符的格式為

運算符地址表達式

(1)?SEG和OFFSET運算符。SEG運算符返回變量或標號所在段的段基值,OFFSET運算符返回變量或標號的段內偏移量。

例如,若VAR是一個已經定義的變量,它所在的邏輯段的段基址是3142H,它在該段的偏移量是120H,那么指令

MOVAX,SEGVAR

MOVBX,OFFSETVAR

就等價于:

MOVAX,3142H

MOVBX,120H或LEABX,VAR

(2)?TYPE運算符。TYPE運算符返回變量或標號的類型屬性值。對于各種類型的變量和標號,它們對應的屬性值如表4-1所示。

(3)?LENGTH運算符和SIZE運算符。

LENGTH運算符返回變量數(shù)據(jù)區(qū)分配的數(shù)據(jù)項總數(shù)。SIZE運算符返回變量數(shù)據(jù)區(qū)分配的字節(jié)個數(shù)。例如,若有如下的數(shù)據(jù)定義:

DAT1DB20H,48

DAT2DW5DUP(2,4)

那么,對于下邊的指令語句,它所完成的操作如注釋所示。

MOVAL,TYPEDAT1 ;AL←1

MOVAH,LENGTHDAT1 ;AH←1

MOVBL,SIZEDAT1 ;BL←1

MOVBH,TYPEDAT2 ;BH←2

MOVCL,LENGTHDAT2 ;CL←5

MOVCH,SIZEDAT2 ;CH←20

2.組合運算符

組合運算符有PTR和THIS兩個運算符。

(

1)?PTR運算符。PTR運算符的功能是對已分配的存儲器地址臨時賦予另一種類型屬性,但不改變操作數(shù)本身的類型屬性,同時保留存儲器地址的段基址和段內偏移量的屬性。它的使用格式如下:

類型PTR地址表達式

其中,地址表達式部分可以是標號、變量或各種尋址方式構成的存儲器地址。對于標號,可以設置的類型有NEAR和FAR;對于變量,可以設置的類型有BYTE、WORD和DWORD。

例如:

MOVWORDPTR[BX],AX ;

將BX所指存儲單元臨時設置為字類型

MOVBYTEPTRDAT,AL ;

將變量DAT臨時設置為字節(jié)類型

JMPFARPTRLPT ;

將標號LPT臨時設置為遠類型

(2)?THIS運算符。THIS運算符用來定義一個新類型的變量或標號。但它只指定變量或標號的類型屬性,并不為它分配存儲區(qū),它的段屬性和偏移屬性與下一條可分配地址的變量或標號屬性相同。

格式:THIS類型

其類型選項與PTR運算符相同。例如:

LABEQUTHISBYTE ;EQU是賦值偽指令,它將表達式的值賦給標號或變量

LAWDW2341H

MOVBL,LAB ;(BL)←41H

MOVAX,LAW ;(AX)←2341H

在這里,變量LAB和LAW具有相同的段基址和偏移地址,但LAB是字節(jié)類型,而LAW是字類型。

3.分離運算符

(1)?

LOW運算符。

格式:LOW表達式

功能:取表達式的低字節(jié)返回。

(2)?

HIGH運算符。

格式:HIGH表達式

功能:取表達式的高字節(jié)返回。

例如:

MOVAL,LOW2238H ;AL←38H

MOVAH,HIGH2238H ;AH←22H

4.2偽指令

匯編語言程序的語句除指令以外還可以由偽操作和宏指令組成。偽操作又稱為偽指令,它們不像機器指令那樣是在程序運行期間由計算機來執(zhí)行的,而是在匯編程序對源程序匯編期間由匯編程序處理的,它們可以完成如處理器選擇、定義程序模式、定義數(shù)據(jù)、分配存儲區(qū)、指示程序結束等功能。偽指令形式上與一般指令相似,但偽指令只是為匯編程序提供有關信息,不產生相應的機器代碼。

4.2.1定義符號的偽指令

有時程序中多次出現(xiàn)同一個表達式,為方便起見,可以用賦值偽操作給表達式賦予一個名字。

1.等值偽指令EQU

格式:

<符號名>

EQU<表達式>

功能:給符號名定義一個值,賦予一個符號名、表達式或助記符。

此后,程序中凡需要用到該表達式之處,就可以用表達式名來代替了??梢?,EQU的引入提高了程序的可讀性,也使其更加易于修改。上式中的表達式可以是任何有效的操作數(shù)格式,可以是任何可以求出常數(shù)值的表達式,也可以是任何有效的助記符。舉例如下:CONSTANT EQU 256;將數(shù)256賦以符號名CONSTANTDATA EQU HEIGHT+12;HEIGHT為一標號,地址表達式賦以符號名DATAALPHA EQU 7BETA EQU ALPHA-2;這是一組賦值偽操作,把7-2=5賦以符號名BETAADDR EQU VAR+BETA ;將VAR+5賦以符號名ADDRB EQU [BP+8] ;變址引用賦以符號名BP8 EQU DS:[BP+8] ;加段前綴的變址引用賦以符號名P8

在EQU語句的表達式中,如果有變量或標號的表達式,則在該語句前應該先給出它們的定義。例如,語句

ABEQU

DATA_ONE+2

必須放在DATA_ONE的定義之后,否則匯編程序將指示出錯。

2.等號偽指令“=”

還有一個與EQU相類似的“=”偽操作也可以作為賦值操作使用。它們之間的區(qū)別是:EQU偽操作中的表達式名是不允許重復定義的,而“=”偽操作則允許重復定義。

例如,EMP

=

6或EMPEQU6都可以使數(shù)6賦給符號名EMP,然而不允許兩者同時使用。但是,語句

EMP=7

EMP=EMP+1

在程序中是允許使用的,因為“=”偽操作允許重復定義。這種情況下,在第一個語句后的指令中,EMP的值為7;而在第二個語句后的指令中,EMP的值為8。

3.解除定義偽指令PURGE

格式:

PURGE<符號1,符號2,…,符號N>

功能:解除指定符號的定義。解除符號定義后,可用EQU重新進行定義。例如:

Y1 EQU 7 ;定義Y1的值為7

PURGE Y1 ;解除Y1的定義

Y1 EQU 36 ;重新定義Y1的值為36

4.2.2定義數(shù)據(jù)的偽指令

這一類偽指令的格式是:

[變量]助記符操作數(shù),…,操作數(shù)[;注釋]

功能:為操作數(shù)分配存儲單元,并用變量與存儲單元建立聯(lián)系。

其中,變量是可有可無的,它用符號地址表示,其作用與指令語句前的標號相同,但它的后面不跟冒號。如果語句中有變量名,則匯編程序使其記為第一個字節(jié)的偏移地址。注釋字段用來說明該偽指令的功能,它也是可有可無的。偽指令格式中的助記符是用來說明所定義的數(shù)據(jù)類型。

這一類偽指令的助記符有以下幾種:

(1)?DB用來定義字節(jié),其后的每個操作數(shù)都占有一個字節(jié)(8位)的存儲單元。

(2)

DW用來定義字,其后的每個操作數(shù)占有一個字(16位,其低位字節(jié)在第一個字節(jié)地址中,高位字節(jié)在第二個字節(jié)地址中)。

(3)

DD用來定義雙字(4個字節(jié)),其后的每個操作數(shù)占有兩個字(32位)。

(4)

DF用來定義3字(6個字節(jié)),其后的每個操作數(shù)占有48位,可用來存放遠地址。這一偽指令只能用于386及其后繼機型中。

(5)

DQ用來定義4字(8個字節(jié)),其后的每個操作數(shù)占有4個字(64位),可用來存放雙精度浮點數(shù)。

(6)?DT用來定義5字(10個字節(jié)),其后的每個操作數(shù)占有5個字,形成壓縮的BCD碼形式。

這些偽指令可以把其后跟著的數(shù)據(jù)存入指定的存儲單元,形成初始化數(shù)據(jù),或者只分配存儲空間而并不存入確定的數(shù)值,形成未初始化數(shù)據(jù)空間。DW和DD偽指令還可存儲地址,DF偽指令則可存儲由16位段地址及32位偏移地址組成的遠地址指針。下面舉例說明。

【例4-2】操作數(shù)可以是常數(shù),或者是表達式(根據(jù)該表達式可以求得一個常數(shù)),如:

DATA_BYTEDB10,4,10H

DATA_WORDDW100,100H,-5

DATA_DWDD3C,0FFFDH

匯編程序可以在匯編期間在存儲器中存入數(shù)據(jù),匯編后的內存分布如圖4.1所示。

圖4.1例4-2的匯編結果

【例4-3】操作數(shù)也可以是字符串,如:

MESSAGEDB‘HELLO’

存儲器存儲情況如圖4.2(a)所示,而DB'AB'?和DW'AB'?的存儲情況分別如圖4.2(b)和(c)所示。

(a)字符串的存儲;(b)DB‘AB’;(c)DW‘AB’圖4.2例4-3的匯編結果

【例4-4】操作數(shù)“?”可以保留存儲空間,但不存入數(shù)據(jù)。例如:

ABCDB0,?,?,0

DEFDW?,52,?

經匯編后的存儲情況如圖4.3所示。

操作數(shù)還可以使用復制操作符(DUPLICATIONOPERATOR)來復制某個(或某些)操作數(shù)。其格式為

REPEAT_COUNTDUP(OPERAND,…,OPERAND)

其中,REPEAT_COUNT可以是一個表達式,它的值應該是一個正整數(shù),用來指定括號中的操作數(shù)的重復次數(shù)。

圖4.3例4-4的匯編結果

【例4-5】使用DUP實現(xiàn)重復定義。

ARRAY1DB2DUP(0,1,2,?)

ARRAY2DB100DUP(?)

經匯編后的存儲情況如圖4.4所示。

由圖可見,例4-5中的第一個語句展開后和語句ARRAY1

DB

0,1,2,?,0,1,2,?是等價的。

圖4.4例4-5的匯編結果

4.2.3定義程序開始和結束的偽指令

在程序的開始部分可以用NAME或TITLE為模塊命名。NAME的格式是:

NAMEMODULE_NAME

匯編程序將以給出的MODULE_NAME作為模塊的名字。如果程序中沒有使用NAME偽操作,則可使用TITLE偽操作,其格式為

TITLETEXT

TITLE偽操作可指定列表文件的每一頁上打印的標題。同時,如果程序中沒有使用NAME偽操作,則匯編程序將用TEXT中的前六個字符作為模塊名。TEXT中最多可有60個字符。如果程序中既無NAME又無TITLE偽操作,則將用源文件名作為模塊名。所以,NAME及TITLE偽操作并不是必要的,但一般經常使用TITLE,以便在列表文件中能打印出標題來。

表示源程序結束的偽操作的格式為

END[LABEL]

其中,標號(LABEL)指示程序開始執(zhí)行的起始地址。如果多個程序模塊相連接,則只有主程序要使用標號,其他子程序模塊只用END而不必指定標號。匯編程序將在遇到END時結束匯編,而程序則將從主模塊的第一個標號處開始執(zhí)行。

4.2.4指令集選擇偽指令

由于80x86的所有處理器都支持8086/8088指令系統(tǒng),而且每一種高檔的機型又都增加了一些新的指令,因此,在編寫程序時要對所用處理器有一個確切的選擇。也就是說,要告訴匯編程序應該選擇哪一種指令系統(tǒng)。這一組偽操作的功能就是確定指令系統(tǒng)。

此類偽操作主要有以下幾種:

(1)?.8086:選擇8086指令系統(tǒng)。

(2)?.286:選擇80286指令系統(tǒng)。

(3)?.286P:選擇保護方式下的80286指令系統(tǒng)。

(4)?.386:選擇80386指令系統(tǒng)。

(5)?.386P:選擇保護方式下的80386指令系統(tǒng)。

(6)?.486:選擇80486指令系統(tǒng)。

(7)?.486P:選擇保護方式下的80486指令系統(tǒng)。

(8)?.586:選擇Pentium指令系統(tǒng)。

(9)?.586P:選擇保護方式下的Pentium指令系統(tǒng)。

有關“選擇保護方式下的xxxx指令系統(tǒng)”的含義是指包括特權指令在內的指令系統(tǒng)。此外,上述偽操作均支持相應的協(xié)處理器指令。

這類偽操作一般放在整個程序的最前面,如不給出,則匯編程序默認值為?.8086指令系統(tǒng)。它們可放在程序中,如程序中使用了一條80486所增加的指令,則可以在該指令的上一行加上?.486。

4.2.5地址計數(shù)器與對準偽操作

1.地址計數(shù)器——$

在匯編程序對源程序匯編的過程中,使用地址計數(shù)器(LOCATIONCOUNTER)來保存當前正在匯編的指令的偏移地址。當開始匯編或在每一段開始時,把地址計數(shù)器初始化為零,以后在匯編過程中,每處理一條指令,地址計數(shù)器就增加一個值,此值為該指令所需要的字節(jié)數(shù)。地址計數(shù)器的值可用$來表示,匯編語言允許用戶直接用$來引用地址計數(shù)器的值,因此指令

JNE$+6

的轉向地址是JNE指令的首地址加上6。當$用在指令中時,它表示本條指令的第一個字節(jié)的地址。在這里,$+6必須是另一條指令的首地址;否則,匯編程序將指示出錯信息。當$用在偽操作的參數(shù)字段時,和它用在指令中的情況不同,它所表示的是地址計數(shù)器的當前值。

【例4-6】$?用法示例。

ARRAY

DW1,2,$+4,3,4,$+4

如匯編時ARRAY分配的偏移地址為0074,則匯編后的存儲區(qū)將如圖4.5所示。

注意:ARRAY數(shù)組中的兩個?$+4得到的結果是不同的,這是由于?$?的值是在不斷變化的緣故。當在指令中用到?$?時,它只代表該指令的首地址,而與?$?本身所在的字節(jié)無關。

圖4.5例4-6的匯編結果

2.ORG偽操作

ORG偽操作用來設置當前地址計數(shù)器的值,其格式為

ORGCONSTANTEXPRESSION 如常數(shù)表達式的值為N,則ORG偽操作可以使下一個字節(jié)的地址成為常數(shù)表達式的值N。例如:

VECTORS SEGMENT

ORG10

VECT1DW47A5H

?ORG20

VECT2DW0C596H

VECTORS ENDS

則VECT1的偏移地址值為0AH,而VECT2的偏移地址值為14H。

常數(shù)表達式也可以表示從當前已定義過的符號開始的位移量,或表示從當前地址計數(shù)器值$開始的位移量。例如:

ORG$+8

可以表示跳過8個字節(jié)的存儲區(qū),亦即建立了一個8字節(jié)的未初始化的數(shù)據(jù)緩沖區(qū)。如程序中需要訪問該緩沖區(qū),則可用LABEL偽操作來定義該緩沖區(qū)的如下變量名:

BUFFERLABELBYTE

ORG$+8

當然,其完成的功能和

BUFFER DB 8 DUP(?)

是一樣的。

3.EVEN偽操作

EVEN偽操作使下一個變量或指令開始于偶數(shù)字節(jié)地址。一個字的地址最好從偶地址開始,所以對于字類型數(shù)組,為保證其從偶地址開始,可以在其前用EVEN偽操作來達到這一目的。

例如:

DATA_SEG SEGMENT

EVEN ;保證地址從偶地址開始

WORD_ARRAYDW 100 DUP(?)

DATA_SEG ENDS

4.?ALIGN偽操作

ALIGN偽操作為保證雙字類型數(shù)組邊界從4的倍數(shù)開始創(chuàng)造了條件,其格式為

ALIGNBOUNDARY

其中,BOUNDARY必須是2的冪,例如:

.DATA

ALIGN 4

ARRAY DB 100 DUP(?)

就可保證ARRAY的值為4的倍數(shù)。當然,ALIGN2和EVEN是等價的。

4.3匯編語言源程序結構

1.完整段定義的程序結構存儲器的物理地址是由段地址和偏移地址組合而成的,匯編程序在把源程序轉換為目標程序時,必須確定標號和變量(代碼段和數(shù)據(jù)段的符號地址)的偏移地址,并且需要把有關信息通過目標模塊傳送給連接程序,以便連接程序把不同的段和模塊連接在一起,形成一個可執(zhí)行程序。為此,需要用段定義偽操作,其格式如下:

SEGMENT_NAME SEGMENT

<語句體>

SEGMENT_NAME ENDS

其中,語句體部分對于數(shù)據(jù)段、附加段和堆棧段來說,一般是存儲單元的定義、分配等偽操作,對于代碼段則是指令及偽操作。

此外,在代碼段還必須明確段和段寄存器的關系,這可用ASSUME偽操作來實現(xiàn),其格式為

ASSUME<段寄存器名>:段名[,<段寄存器名>:段名,…]

ASSUME<段寄存器名>:NOTHING

其中,段寄存器名必須是CS、DS、ES和SS(對于386及其后繼機型還有FS和GS),而段名則必須是由SEGMENT定義的段中的段名。ASSUMENOTHING則可取消前面由ASSUME所指定的段寄存器的對應關系。

由于ASSUME偽操作只是指定某個段分配給哪一個段寄存器,它并不能把段地址裝入段寄存器中,要把段地址裝入段寄存器中,就要求在代碼段中必須有對段地址裝入相應的段寄存器中的指令。例如,在上面的程序中,分別用兩條MOV指令完成這一操作。如果程序中有堆棧段,也需要把段地址裝入SS中。但是,代碼段CS不需要這樣做,這一操作是在程序初始化時完成的。

為了對段定義作進一步的控制,SEGMENT偽操作添加了類型及屬性說明,其格式如下:

<段名>

SEGMENT

[定位類型][組合類型][使用類型][類別]

<段名>

ENDS

在一般情況下,這些說明可以不用。但是,當需要用連接程序把本程序與其他程序模塊相連接時,就需要使用這些說明。

2.對段定義的進一步說明

1)定位類型(ALIGN_TYPE)

定位類型用于說明段的起始地址應有怎樣的邊界值,其取值可以是:

PARA:指定段的起始地址必須從小段邊界開始,即段起始地址最低位必須為0。這樣,偏移地址可以從0開始。

BYTE:該段可以從任何地址開始,這樣,起始偏移地址可能不是0。

WORD:該段必須從字的邊界開始,即段起始地址必須為偶數(shù)。

DWORD:該段必須從雙字邊界開始,即段起始地址的最低位必須為4的倍數(shù)。

PAGE:該段必須從負的邊界開始,即段起始地址的最低兩個十六進制數(shù)位必須為0(該地址能被256整除)。

定位類型的默認項是PARA,即未指定定位類型時,匯編程序默認為PARA。

2)組合類型(COMBINE_TYPE)

組合類型用于說明程序連接時段的合并方法,其取值可以是:

PRIVATE

:該段為私有段,在連接時不與其他模塊中的同名段合并。

PUBLIC:該段連接時可以把不同模塊中的同名段相連接而合并為一個段,其連接次序由連接命令指定。

COMMON:該段在連接時可以把不同模塊中的同名段重疊而形成一個段,由于各同名分段有相同的起始地址,因此會產生覆蓋。

ATEXPRESSTION:使段地址為表達式所計算出來的16位值,但它不能用來指定代碼段。

MEMORY:與PUBLIC同義。

STACK:把不同模塊中的同名段組合而形成一個堆棧段,該段的長度為原有各堆棧段長度的總和,原有各段之間并無PUBLIC所連接段中的間隙,而且棧頂可自動指向連接后形成的大堆棧段的棧頂。

組合類型的默認項是PRIVATE。

3)使用類型(USE_TYPE)

使用類型只適用于386及其后繼機型,它用來說明是使用16位尋址方式還是使用32位尋址方式。其取值可以是:

USE16:使用16位尋址方式。

USE32:使用32位尋址方式。

當使用16位尋址方式時,段長不超過64?KB,地址的形式是16位段地址和16位偏移地址組合;當使用32位尋址方式時,段長可達4?GB,地址的形式是16位段地址和32位偏移地址組合??梢钥闯?,在實模式下,應該使用USE16。

使用類型的默認項是USE16。

4)類別名(‘CLASS’)

在單引號中給出連接時組成段組的類型名。類別說明并不能把相同類別的段合并起來,但在連接后形成的裝入模塊中,可以把它們的位置靠在一起。

4.4匯編語言程序的上機過程

在計算機上運行匯編語言程序的步驟是:

(1)用編輯程序建立?.ASM源文件;

(2)用MASM程序把?.ASM文件匯編成?.OBJ文件;

(3)用LINK程序把?.OBJ文件連接成.EXE文件;

(4)用DOS命令直接鍵入文件名就可執(zhí)行該程序。

目前常用的匯編程序有Microsoft公司推出的宏匯編程MASM(MACROASSEMBLER)和BORLAND公司推出的TASM(TURBOASSEMBLER)兩種。本書采用MASM5.0版來說明匯編程序所提供的偽操作和操作符,操作流程(匯編語言程序的建立及匯編過程)如圖4.6所示。

圖4.6匯編語言程序的建立及匯編過程

說明:圖4.6中□表示操作使用的工具;○表示操作得到的文件。

匯編程序的主要功能是:

(1)檢查源程序語法是否正確。

(2)測出源程序中的語法錯誤,并給出出錯信息。

(3)產生源程序的目標程序,并可給出列表文件(同時列出匯編語言和機器語言的文件,稱為?.LST文件)。

(4)展開宏指令。

4.4.1建立匯編語言的工作環(huán)境

為運行匯編語言程序,至少要在磁盤上提供以下文件:

(1)編輯程序,如EDIT.EXE;

(2)匯編程序,如MASM.EXE;

(3)鏈接程序,如LINK.EXE;

(4)調試程序,如DEBUG.COM。

必要時,還要提供CREF.EXE、EXR2BIN.EXE等文件。

4.4.2匯編語言源程序上機過程

1.建立匯編源程序?.ASM文件

【例4-7】把40個字母A的字符串從源緩沖區(qū)傳送到目的緩沖區(qū)。

可以用編輯程序EDIT在磁盤上建立如下的源程序EXAM.ASM。

2.匯編產生?.OBJ文件

源文件建立后,就要用匯編程序對源文件匯編,匯編后產生二進制的目標文件(.OBJ文件),其操作與匯編程序回答如下:

3.鏈接產生?.EXE文件

匯編程序已產生出二進制的目標文件(.OBJ),但?.OBJ文件并不是系統(tǒng)可執(zhí)行的文件,因此還必須使用鏈接程序(LINK)把?.OBJ文件轉換為系統(tǒng)可執(zhí)行的?.EXE文件。當然,如果一個程序是由多個模塊組成,也應該通過LINK把它們鏈接在一起,操作方法及機器回答如下:

LINK程序有兩個輸入文件?.OBJ和?.LIB。.OBJ是我們需要鏈接的目標文件,.LIB則是程序中需要用到的庫文件,如無特殊需要,則應對[.LIB]:直接回車。LINK程序有兩個輸出文件,一個是?.EXE文件,這是我們所需要的,應對[EXAM.EXE]:直接回車,這樣就在磁盤上建立了該可執(zhí)行文件。LINK的另一個輸出文件為?.MAP文件,它是鏈接程序的列表文件,又稱為鏈接映像(LINKMAP),它給出了每個段在存儲器中的分配情況。

鏈接程序給出的無堆棧段的警告性錯誤并不影響程序的運行。所以,到此為止,鏈接過程已經結束,可以在操作系統(tǒng)下執(zhí)行EXAM程序了。

4.程序的調試和執(zhí)行

在建立了?.EXE文件后,就可以直接在操作系統(tǒng)中執(zhí)行程序,程序如下:

C:\>EXAM↙

C:\>_

程序運行結束并返回DOS。如果用戶程序已直接把結果在終端上顯示出來,那么程序已經運行結束,結果也已經得到。但是,如果EXAM程序并未顯示出結果,這就要使用調試程序進行分析。常用的調試工具軟件為DEBUG,見附錄2。

5.生成?.COM文件

.COM文件也是一種可執(zhí)行文件,由程序本身的二進制代碼組成,它沒有?.EXE文件所具有的包括有關文件信息的標題區(qū)(HEADER),因此它占有的存儲空間比?.EXE文件要小。.COM文件不允許分段,它所占有的空間不允許超過64KB,因而只能用來編制較小的程序。由于其小而簡單,因此其裝入速度比?.EXE文件要快。

使用?.COM文件時,程序不分段,其入口點(開始運行的起始點)必須是100H(其前的256個字節(jié)為程序段前綴所在地),且不必設置堆棧段。在程序裝入時,由系統(tǒng)自動把SP建立在該段之末。對于所有的過程,則應定義為NEAR。

用戶可以通過操作系統(tǒng)下的EXE2BIN程序來建立?.COM文件,操作方法如下:

C:\>EXE2BINFILENAMEFILENAME.COM↙

注意,上行中的第一個FILENAME給出了已形成的?.EXE文件的文件名,但不必給出文件擴展名;第二個FILENAME即為所要求的?.COM文件的文件名,它必須帶有文件擴展名?.COM,這樣就形成了所要的?.COM文件。

此外,.COM文件還可以直接在調試程序DEBUG中用A或E命令建立,對于一些短小的程序,這也是一種相當方便的方法。

4.5匯編語言程序設計

4.5.1流程圖的組成借助于流程圖可以清晰地把程序思路表達出來,有助于編寫正確的程序。流程圖對程序設計人員,特別是初學者來說是一種非常有用的工具。流程圖用一些圖框表示各種操作,用圖形表示算法,直觀形象,易于理解。美國國家標準化協(xié)會ANSI(American

National

StandardInstitute)規(guī)定了一些常用的流程圖,已被世界各國程序工作者普遍采用。

流程圖一般由六種成分組成,如圖4.7所示。

圖4.7流程圖的組成成分

1)執(zhí)行框(矩形框)

執(zhí)行框的作用是表示一段程序或一個模塊的功能,對于結構化程序,一個執(zhí)行框只有一個入口和一個出口。

2)判別框(菱形框)

判別框的作用是對一個給定的條件進行判斷,根據(jù)給定的條件是否成立來決定如何執(zhí)行其后的操作。它有一個入口,兩個出口,表示比較、判斷條件。

3)開始框和結束框

開始框和結束框表示程序的起始和結束。

4)指向線

指向線表示程序執(zhí)行的順序。

5)連接點(小圓圈)

連接點用于將畫在不同地方的流程線連接起來。例如,圖4.8中,有兩個以①為標志的連接點,它表示這兩個點是互相連接在一起的。實際上它們是同一個點,只是當在紙張上畫不下時才分開來畫。使用連接點可以避免流程線的交叉或過長,使流程圖清晰。

圖4.8流程圖的繪制示意

可以看出,流程圖是表示算法的較好工具。一個流程圖包括以下幾部分:

(1)表示相應操作的框;

(2)帶箭頭的流程線;

(3)框內外必要的文字說明。

繪制流程線時不要忘記畫箭頭,因為它反映了流程執(zhí)行的先后次序,如不畫出箭頭則難以判定各框的執(zhí)行次序。

4.5.2順序程序結構

順序程序結構是指完全按順序逐條執(zhí)行的指令序列,這種程序結構在程序段中大量存在。順序結構程序是最簡單的程序。在順序結構程序中,指令按照先后順序一條一條執(zhí)行。

注意:

(1)本程序采用了DOS中斷調用的4CH號功能來退出程序段運行,返回DOS現(xiàn)場。這是一種常用的執(zhí)行程序返回DOS現(xiàn)場的方法。

(2)本例可顯示輸出。

4.5.3分支程序設計

1.分支程序結構形式

分支程序結構可以有兩種形式,如圖4.9所示。它們分別相當于高級語言中的IF_THEN_ELSE語句和CASE語句,適用于要求根據(jù)不同條件作不同處理的情況。IF_THEN_ELSE語句可以引出兩個分支,CASE語句則可以引出多個分支。不論哪一種形式,它們的共同特點是:運行方向是向前的,在某一種特定條件下,只能執(zhí)行多個分支中的一個分支。

(a)?IF_THEN_ELSE結構(b)?CASE結構圖4.9分支程序的結構形式

2.分支程序設計方法

程序的分支一般用條件轉移指令來產生,利用轉移指令不影響條件碼的特性,連續(xù)地使用條件轉移指令可使程序產生多個不同的分支。

【例4-9】TABLE是一字節(jié)數(shù)組的首地址,長度為100。統(tǒng)計此數(shù)組中正數(shù)、0及負數(shù)的個數(shù),并分別放在COUNT1、COUNT2和COUNT3變量中。其流程圖如圖4.10所示。

圖4.10例4-9流程圖

本程序段在開始時出現(xiàn)了兩次壓棧操作,即PUSHDS和PUSHAX((AX)

=

0)。本程序段是一個FAR屬性的子程序,在程序結束執(zhí)行RET時將引起兩次出棧操作,會使(CS)內容等于未執(zhí)行本程序前的值,(IP)?=

0。在(CS):(IP)位置有一段程序,功能就是退出程序段運行,返回DOS現(xiàn)場。這是第二種執(zhí)行程序返回DOS現(xiàn)場的方法。

4.5.4循環(huán)程序設計

1.循環(huán)程序結構

循環(huán)程序結構可以總結為兩種結構形式,如圖4.11所示。一種是DOWHILE(當形)結構形式;另一種是DOUNTIL(直到形)結構形式。

(a)?DOWHILE結構(b)?DOUNTIL結構圖4.11循環(huán)程序的結構形式

1)

DOWHILE結構

DOWHILE結構把對循環(huán)控制條件的判斷放在循環(huán)的入口,先判斷條件,滿足條件就執(zhí)行循環(huán)體,否則就退出循環(huán),如圖4.11(a)所示。

2)

DOUNTIL結構

DOUNTIL結構把對循環(huán)控制條件的判斷放在循環(huán)的出口,先執(zhí)行循環(huán)體,然后判斷控制條件,不滿足條件則繼續(xù)執(zhí)行循環(huán)操作,一旦滿足條件則退出循環(huán),如圖4.11(b)所示。

這兩種結構可以根據(jù)具體情況選擇使用。如果有循環(huán)次數(shù)等于0的情況,則應選擇DOWHILE結構,否則使用DOUNTIL結構。不論哪一種結構形式,循環(huán)程序都可由如下四部分組成:

(1)循環(huán)初始化。初始化完成設置循環(huán)次數(shù)的計數(shù)值或其他條件,設置循環(huán)初始地址,為循環(huán)體正常工作而建立初始狀態(tài)等。

(2)循環(huán)體。循環(huán)體是循環(huán)程序的主體,該部分是為完成程序功能而設計的主要程序段。

(3)循環(huán)修改。循環(huán)修改是調整計數(shù)值或內存地址的部分,保證每一次重復(循環(huán))時,參加執(zhí)行的信息能發(fā)生有規(guī)律的變化而建立的程序段。

(4)循環(huán)控制。循環(huán)控制本來應該屬于循環(huán)體的一部分,由于它是循環(huán)程序設計的關鍵,因此要對它作專門的討論。每個循環(huán)程序必須選擇一個循環(huán)控制條件來控制循環(huán)的運行和結束,而合理地選擇該控制條件就成為循環(huán)程序設計的關鍵問題。有時循環(huán)次數(shù)是已知的,此時可以用循環(huán)次數(shù)作為循環(huán)的控制條件,LOOP指令使這種循環(huán)程序設計能很容易地實現(xiàn)。

2.循環(huán)程序設計方法

【例4-10】設計一個程序,完成從1連加到100(即1

+

2

+

+

99

+

100)的操作,結果保存在數(shù)據(jù)段的SUM單元。

分析:這樣的問題如果采用順序程序設計,至少要一百條指令,并且程序的結構性和可讀性差,而采用循環(huán)程序設計就會簡潔明了。程序清單如下:

注意:

(1)本程序段采用了第三種退出方式,程序運行結束將由于執(zhí)行HLT指令而進入停機狀態(tài),當鍵入Ctrl?+

Break組合鍵(鍵盤中斷)后,返回DOS現(xiàn)場。

(2)用DEBUG跟蹤,會發(fā)現(xiàn)(SUM)?=

13BAH。

【例4-11】試編制一個把SUM的二進制數(shù)用十六進制數(shù)的形式在屏幕上顯示的程序段,作為轉換輸出功能部分,插入到例4-10中程序的“;********”位置。重新運行例4-10程序,就會在屏幕上顯示出運算結果。

根據(jù)題意,將SUM內容送到BX中,從左到右每四位為一組在屏幕上顯示出來,每次循環(huán)顯示一個十六進制數(shù)位,計數(shù)初值為4。程序框圖如圖4.12所示。采用循環(huán)移位的方式把所要顯示的4位二進制數(shù)移到最右面,以便做數(shù)字到字符的轉換工作。另外,由于數(shù)字0~9的ASCII值為30H~39H,而字母A~F的ASCII值為41H~46H,因此在把4位二進制數(shù)加上30H后,還需作一次判斷,如果是字符A~F,則還應加上7才能顯示出正確的十六進制數(shù)。以BINIHEX.ASM為文件名建立“二進制到十六進制數(shù)轉換程序”源文件。

圖4.12二進制到十六進制數(shù)轉換程序的框圖

在程序中沒有使用LOOP指令,這是因為循環(huán)移位指令要使用CL寄存器,而LOOP指令要使用CX寄存器,為了解決CX寄存器的沖突問題,這里用CH寄存器存放循環(huán)計數(shù)值,而用DEC及JNZ兩條指令完成LOOP指令的功能。這說明,使用計數(shù)值控制循環(huán)結束也可以不用LOOP指令。當然也可以把計數(shù)值初始化為0,用每循環(huán)一次加1然后比較次數(shù)是否達到要求的方法來實現(xiàn),或者仍用LOOP指令,而用堆棧保存其中的一個信息(如計數(shù)值)來解決CX寄存器的沖突問題等??傊?,程序設計是很靈活的,只要算法和指令的使用沒有錯誤,都可以達到目的。

二進制到十六進制轉換程序如下:

注意:由于上述匯編語言格式不完全,因此該程序段不能單獨運行。

4.5.5子程序結構形式與操作

1.子程序定義

可把具有獨立功能的程序段定義為子程序,供其他程序調用(類似于C語言的函數(shù))。子程序定義偽操作用在子程序的前后,使整個子程序形成清晰的、具有特定功能的代碼塊。

子程序定義的語法格式為

<子程序名>

PROC <屬性>

RET

<子程序名>ENDP

其中,子程序名為標識符,它又是子程序入口的符號地址,它的寫法與標號的寫法相同;屬性(Attribute)是指類型屬性,它可以是NEAR或FAR。

如前所述,CALL和RET指令都有NEAR和FAR的屬性,段內調用使用NEAR屬性,但可以不顯示地寫出,段間調用使用FAR屬性。為了使用戶的工作更加方便,80x86的匯編程序用PROC偽操作的類型屬性來確定CALL和RET指令的屬性。也就是說,如果所定義的子程序是FAR屬性的,那么對它的調用和返回一定都是FAR屬性;如果所定義的子程序是NEAR屬性的,那么對它的調用和返回也一定是NEAR屬性。

這樣,用戶只需在定義子程序時考慮它的屬性,而CALL和RET的屬性可以由匯編程序來確定。用戶確定子程序屬性的原則很簡單,即

(1)如調用程序和子程序在同一個代碼段中,則使用NEAR屬性;

(2)如調用程序和子程序不在同一個代碼段中,則使用FAR屬性。

由于調用程序MAIN和子程序SUBR1在同一代碼段中,因此SUBR1定義為NEAR屬性。這樣,MAIN中對SUBR1的調用和SUBR1中的RET就都是NEAR屬性。但是一般來說,主程序MAIN應定義為FAR屬性,這是由于匯編系統(tǒng)把MAIN程序也看做是DOS調用的一個子程序,因而DOS對MAIN的調用以及MAIN中的RET就是FRA屬性。當然,CALL和RET的屬性是匯編程序確定的,用戶只需正確選擇PROC的屬性就可以了。

例4-12的情況也可以寫成如下程序:

也就是說,子程序定義也可以嵌套,一個子程序定義中可以包括多個子程序定義。

SUBT是一個子程序,它在兩處被調用,一處是與SEGX同在段內,另一處是在SEGY段內。為此,SUBT必須具有FAR屬性以適應SEGY段調用的需要。SUBT既然有FAR屬性,則不論在SEGX段還是SEGY段中,對SUBT的調用就都具有FAR屬性了,這樣不會發(fā)生什么錯誤。反之,如果這里的SUBT使用了NEAR屬性,則在SEGY段內對它的調用就會出錯。

2.子程序的調用和返回

子程序的正確執(zhí)行是由子程序的正確調用和正確返回保證的,80x86的CALL和RET指令完成的就是調用和返回的功能。為保證其正確性,除PROC的屬性要正確選擇外,還應該注意子程序運行期間的堆棧狀態(tài)。由于執(zhí)行CALL時已使返回地址入棧,因此執(zhí)行RET時應該使返回地址出棧,如果子程序中不能正確使用堆棧而造成執(zhí)行RET前SP并未指向進入子程序時的返回地址,則必然會導致運行出錯。因此,子程序中對堆棧的使用應該特別小心,以免發(fā)生錯誤。

3.現(xiàn)場保護與現(xiàn)場恢復

由于主程序和子程序通常是分別編制的,因此它們所使用的寄存器往往會發(fā)生沖突。如果主程序調用子程序之前的某個寄存器內容在從子程序返回后還有用,而子程序又恰好使用了同一個寄存器,這就破壞了該寄存器的原有內容,因而會造成程序運行錯誤,這是不允許的。為避免這種錯誤的發(fā)生,在進入子程序后,就應該把子程序所需要使用的寄存器內容保存在堆棧中,此過程稱作現(xiàn)場保護;而在退出子程序前把寄存器內容恢復原狀,此過程稱作現(xiàn)場恢復?,F(xiàn)場保護與現(xiàn)場恢復分別使用壓棧和彈出指令實現(xiàn)。例如:

在設計子程序時,應仔細考慮哪些寄存器是必須保護的,哪些寄存器是不必要保護的。一般來說,子程序中用到的寄存器是應該保護的。但是,如果使用寄存器在主程序和子程序之間傳送參數(shù)的話,則這種寄存器就不一定需要保護,特別是用來向主程序回送結果的寄存器,就更不應該因保存和恢復寄存器而破壞了應該向主程序傳送的信息。

從80286

CPU開始使用的PUSHA/POPA指令以及從80386CPU開始的高檔微機使用的PUSHAD/POPAD指令為子程序中保存和恢復寄存器內容提供了有力的支持。

4.子程序嵌套

主程序調用子程序,子程序還可以調用其他子程序,這就是子程序的嵌套調用,子程序可以多重嵌套調用。

【例4-14】設從BUF開始存放若干無符號字節(jié)數(shù)據(jù),找出其中的最小值并以十六進制形式輸出。

分析:本題用子程序SEARCH來求最小數(shù)字節(jié)數(shù)并輸出,再調用一個子程序輸出1位十六進制數(shù)。由于數(shù)據(jù)多,因此可以利用子程序的嵌套。

注意:本例有顯示輸出子程序部分,上機更直觀。

4.5.6BIOS中斷調用

1.

BIOS中斷調用概述

BIOS(BasicInput/OutputSystem)是IBM-PC的監(jiān)控程序,它固化在微機主板的ROM中,它的內容主要有系統(tǒng)測試程序(POST)、初始化引導程序(BOOT)、I/O設備的基本驅動程序和許多常用程序模塊,它們一般以中斷服務程序的形式存在。

圖4.13是用戶程序和操作系統(tǒng)關系示意圖。由圖可見,BIOS程序直接建立在硬件基礎上,磁盤操作系統(tǒng)(DOS)和其他操作系統(tǒng)建立在BIOS基礎上,各種高級語言則建立在操作系統(tǒng)基礎上。用戶程序可以使用高級語言,也可以調用DOS或其他操作系統(tǒng),還可以調用BIOS,甚至直接指揮硬件設備。

圖4.13用戶程序和操作系統(tǒng)關系示意圖

通常,應用程序調用DOS提供的系統(tǒng)功能完成輸入/輸出或其他操作,這樣做用戶可以少考慮硬件,實現(xiàn)起來容易。應用程序直接對硬件編程的優(yōu)點是程序的效率高,缺點是需要程序員對硬件性能有較深的了解。

BIOS中斷程序處于DOS功能調用和硬件環(huán)境之間,和DOS功能調用相比,其優(yōu)點是效率高,缺點是編程相對復雜;和直接對硬件編程相比,優(yōu)點是實現(xiàn)相對容易,缺點是效率相對低。在下列情況下可考慮使用BIOS中斷。

(1)有些功能DOS沒有提供,但BIOS提供了;

(2)有些場合無法使用DOS功能調用;

2.

BIOS中斷調用方法

IOS的調用就是人們借用每一臺計算機中BIOS固有的I/O操作程序來方便地解決自己的問題,由于它已經在計算機中了,因此人們不必再把它寫入自己的程序,只要指明它的操作位置就可以了。

1)

BIOS調用的基本操作

由于BIOS中的每一種功能調用往往包含不同的幾個操作細節(jié),所以調用時需要說明三部分,基本步驟如下:

(1)設置分功能號:按實現(xiàn)的操作功能的要求,給指定寄存器(通常為AH)送入分功能號。

(2)置入口參數(shù):按操作要求,給寄存器填寫相應參數(shù)的內容(某些調用無參數(shù))。

(3)使用中斷語句INTn:執(zhí)行調用的功能,其中n為中斷號。

(4)分析出口參數(shù)。

例如:

MOVAH,0 ;分功能號為0

MOV

AL,10H ;置入口參數(shù)

NT1AH ;1AH為中斷號,功能為讀時間計數(shù)器的值

注意:某些BIOS調用可能沒有出口參數(shù),這時省略第(4)步操作。

2)

BIOS打印功能調用

BIOSI7H中斷指令提供了由AH寄存器指定的三種不同的打印操作。

(1)?BIOS中斷17H的功能0是打印一個字符。將要打印輸出的字符放在AL中,打印機號放在DX中,BIOS最多允許連接三臺打印機,機號分別為0,1和2。如果只有一臺打印機,那么默認是0號打印機,打印機的狀態(tài)信息被回送到AH寄存器。

(2)?BIOS17H的功能1是初始化打印機。初始化打印機并回送打印機狀態(tài)到AH寄存器。如果把打印機開關關上然后又打開,則打印機各部分復位到初始值。此功能和打開打印機時的作用一樣。在每個程序的初始化部分可以用17H的功能1來初始化打印機。

(3)?BIOS17H的功能2是把狀態(tài)字節(jié)讀入AH寄存器中。打印機的狀態(tài)字節(jié)如圖4.14所示。

圖4.14打印機的狀態(tài)字節(jié)

3)

BIOS串行通信口功能

微機通過串行接口實現(xiàn)硬件連接提供了一種比較靈活的通信方法,即通過INT14H調用ROMBIOS串行通信口中斷服務程序。該中斷服務程序的功能包括將串行口初始化為指定的字節(jié)結構和傳輸速率,檢查控制器的狀態(tài),讀/寫字符等。具體功能設置如表4-2所示。

INT14H的AH?=

0功能把指定的串行通信口初始化為希望的波特率、奇偶性、字長和終止位的位數(shù)。這些初始化參數(shù)設置在AL寄存器中,其各位的含義如圖4.15所示。

圖4.15串行通信口初始化參數(shù)

【例4-15】要求0號通信口的傳輸率為2400波特,字長為8位,終止位為1位,無奇偶校驗。

MOVAH,0 ;串行通信口初始化

MOVAL,0A3H ;0A3H?=?10100011B

MOVDX,0 ;指向COM1

INT14H ;調用BIOS

返回參數(shù)中通信口狀態(tài)字節(jié)各位置1的含義如圖4.16所示。

圖4.16串行通信口狀態(tài)字節(jié)

在接收和發(fā)送過程,錯誤狀態(tài)位(1,2,3,4位)一旦被置為1,則讀入的接收數(shù)據(jù)已不是有效數(shù)據(jù),所以在串行通信應用程序中,應檢測數(shù)據(jù)傳輸是否出錯。

奇偶錯:通信線上(尤其是用電話線傳輸時)的噪音引起某些數(shù)據(jù)位的改變,產生奇偶錯。通常檢測出奇偶錯時,要求正在接收的數(shù)據(jù)至少應重新發(fā)送一段。

超越錯:在上一個字符還未被處理機取走,又有字符要傳送到數(shù)據(jù)寄存器里時,就會引起超越錯。如果處理機處理字符的速度小于單行通信口的波特率,則會產生這種錯誤。

幀格式錯:當接收/發(fā)送器未接收到一個字符數(shù)據(jù)的停止位時,會引起幀格式錯。這種錯誤可能是由于通信線上的噪音引起停止位的丟失,或者是由于接收方和發(fā)送方初始化不匹配而造成的。

間斷:間斷有時候并不能算是一個錯誤,而是為某些特殊的通信環(huán)境設置的“空格”狀態(tài)。當間斷位為1時,說明接收的“空格”狀態(tài)超過了一個完整的數(shù)據(jù)字傳輸時間。

PS/2以及所有的PC,AH?=

04功能允許程序員將波特率設置為19?200,數(shù)據(jù)位的長度可以設置為5、6、7或8位,而不像AH?=?0功能那樣只能設置成7或8位。

4.5.7

DOS功能調用

1.

DOS功能調用概述

8086/8088指令系統(tǒng)中,有一種軟中斷指令INTn。每執(zhí)行一條軟中斷指令,就調用一個相應的中斷服務程序。當n?=

5~1FH時,調用BIOS中的服務程序,一般稱作系統(tǒng)中斷調用;當n?=

20~3FH時,調用DOS中的服務程序,稱作功能調用。其中,INT21H是一個具有調用多種功能的服務程序的軟中斷指令,故稱其為DOS系統(tǒng)功能調用。

2.

DOS功能調用方法

1)

DOS軟中斷指令(INT20H~INT27H)

DOS軟中斷功能、入口及出口參數(shù)見表4-3。表中的入口參數(shù)是指在執(zhí)行軟中斷指令前有關寄存器必須設置的值,出口參數(shù)記錄的是執(zhí)行軟中斷以后的結果及特征,供用戶分析使用。

DOS中斷的使用方法是:首先按照DOS中斷的規(guī)定,輸入入口參數(shù),然后執(zhí)行INT指令,最后分析出口參數(shù),如下所示:

表4-3中INT22H、INT23H和INT24H用戶不能直接調用。例如,INT23H只有當同時按下Ctrl和Break鍵時才形成DOS的23H號調用,其功能是:終止正在運行的程序,返回操作系統(tǒng)。INT25H為絕對讀盤,INT26H為絕對寫盤,這兩條軟中斷的調用需要用戶熟知磁盤結構,準確指出讀/寫的扇區(qū)號、扇區(qū)數(shù)、磁盤驅動器號,還需要知道與磁盤交換信息的內存緩沖區(qū)的首地址。因此,這種讀/寫磁盤的方式較落后,除特殊用途外,基本上已不采用。

INT20H是兩字節(jié)指令,它的作用是終止正在運行的程序,返回操作系統(tǒng)。這種終止程序的方法只適用于?.COM文件,而不適用于?.EXE文件。

INT27H指令的作用是終止正在運行的程序,返回操作系統(tǒng),被終止的程序駐留在內存中作為DOS的一部分,它不會被其他程序覆蓋。在其他用戶程序中,可以利用軟中斷來調用這個駐留的程序。

2)

DOS系統(tǒng)功能調用(INT21H)

系統(tǒng)功能調用INT21H是一個有100多個子功能的中斷服務程序,這些子功能的編號稱為功能號。INT21H的功能大致可以分為四個方面:設備管理、目錄管理、文件管理和其他。設備管理主要包括鍵盤輸入、顯示器輸出、打印機輸出、串行設備輸入/輸出、初始化磁盤、選擇當前磁盤、取剩余磁盤空間等。目錄管理主要包括查找目錄項、查找文件、置/取文件屬性、文件改名等。

系統(tǒng)功能調用(INT21H)的使用方法如下:

下面主要介紹INT21H的基本功能。

(1)鍵盤輸入的功能調用。IBM-PC及PC/XT鍵盤上的按鍵分為三種類型:

第一類是字符鍵,如字母、數(shù)字、字符等。按下此類鍵,即可輸入此鍵相應的編碼。

第二類是功能鍵,如Backspace、Home、End、Delete、PgUp、PgDn、F1~F10等。按下此類鍵,可以產生一個動作。例如,按下Backspace可以使光標向左移動一個位置。

第三類是組合鍵及雙態(tài)鍵,如Shift、Alt、Ctrl、Insert、NumLock、CapsLock、ScrollLock等。使用這些鍵能改變其他鍵所產生的字符碼。

①掃描碼與字符碼。

鍵的掃描碼——鍵盤的每一個鍵都有一對掃描碼,掃描碼用一個字節(jié)表示。低7位是掃描碼的數(shù)字編碼01~83,即01H~53H,最高位BIT7表示鍵的狀態(tài)。當某鍵按下時,掃描碼的BIT7

=

0,稱為通碼,當此鍵放開時,掃描碼的BIT7

=

1,稱為斷碼。通碼和斷碼的值相差80H。

鍵的字符碼——鍵的字符碼是鍵的ASCII碼或擴充碼,見表1-4ASCII字符編碼表。

②檢查鍵盤狀態(tài)。DOS系統(tǒng)功能調用中的功能1、7、8、A、B、C等都與鍵盤有關,包括單字符輸入、字符串輸入和鍵盤狀態(tài)檢驗等。

DOS系統(tǒng)功能調用的0BH號功能可以檢查是否有字符鍵入。如果有鍵按下,使AL

=

FFH,否則AL

=

00H。這個調用十分有用,例如,有時要求程序保持運行狀態(tài),而不是無限期等待鍵盤輸入,但又要靠用戶按任意一鍵使程序結束或退出循環(huán)時,就必須使用0BH號調用。

【例4-16】檢查鍵盤狀態(tài)。

LOOP:

MOVAH,0BH

INT21H ;檢查鍵盤狀態(tài)

INCAL

JNZLOOP ;無鍵入字符,則循環(huán)

RET ;有鍵入字符,則停止循環(huán)返回

③單字符輸入。功能1、7、8都可以直接接收鍵入的字符。程序中常常利用這些功能,回答程序中的提示信息,或選擇菜單中的可選項以執(zhí)行不同的程序段。用戶還可以利用功能7、8不回顯的特性,鍵入需要保密的信息。

④字符串輸入。用戶程序經常需要從鍵盤上接收一串字符。0AH號功能可以接收鍵入的字符串將其存入內存中用戶定義的緩沖區(qū)。緩沖區(qū)結構如圖4.17所示。緩沖區(qū)第一字節(jié)為用戶定義的最大鍵入字符數(shù),若用戶鍵入的字符數(shù)(包括回車符)大于此數(shù),則機器鈴響且光標不再右移,直到鍵入回車符為止。緩沖區(qū)第二字節(jié)為實際鍵入的字符數(shù)(不包括回車符),由DOS自動填入。從第三字節(jié)開始存放鍵入的字符,顯然,緩沖區(qū)的大小等于最大字符數(shù)加2。具體實例如例4-18所示。

圖4.17用戶定義的緩沖區(qū)

(2)顯示器(CRT)輸出

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論