子程序與宏指令設計_第1頁
子程序與宏指令設計_第2頁
子程序與宏指令設計_第3頁
子程序與宏指令設計_第4頁
子程序與宏指令設計_第5頁
已閱讀5頁,還剩124頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

為了程序共享或模塊化設計的需要,

可以把一段公共語句序列設計成子程序或

宏指令的形式。

6.1子程序結(jié)構(gòu)及設計方法

6.2子程序參數(shù)傳遞

6.3嵌套與遞歸子程序

6.4宏指令

6.5宏指令庫

6.6重復偽指令

6.7條件偽指令

工6.1子程序結(jié)構(gòu)及設計方法

6.1.1含有子程序的程序結(jié)構(gòu)

在匯編語言中用過程定義偽指令定

義子程序。過程定義偽指令格式:

過程名PROC屬型

過程名ENDP

調(diào)用程序和子程序在同一個代碼段的程

序結(jié)構(gòu)(子程序類型可缺省,注意END后必須

跟空程序名)

CODESEGMENT

MAINPROCFAR

???

CALLSUB1

RET

MAINENDP

SUB1PROC

RET

SUB1ENDP

CODEENDS

ENDMAIN

-馬調(diào)用程序和子程序在不同段的程序結(jié)構(gòu)

森0B繆被段間調(diào)用又被段內(nèi)調(diào)用,必須是FAR屬性

C知季顯式說明是FAR屬性)

■-W/

CODE1SEGMENT

MAINPROCFAR

CALLFARPTRSUB2

RET

MAINENDP

CODE1ENDS

C0DE2SEGMENT

SUB1PROCFAR

CALLFARPTRSUB2

RET

SUB1ENDP

SUB2PROCFAR

RET

SUB2ENDP

C0DE2ENDS

ENDMAIN

Qr.2設計子程序時應注意的問題

1.子程序說明

2.寄存器的保存與恢復

3.密切注意堆棧狀態(tài)

-

6.2子程序參數(shù)傳遞

可以通過給子程序傳遞參數(shù)使其更

通用。常用的參數(shù)傳遞方法如下:通過

寄存器傳遞;若調(diào)用程序和子程序在同

模塊(源程序)中,子程序可以直接訪

問模塊中的變量;通過地址表傳遞參數(shù)

地址;通過堆棧傳遞參數(shù)或參數(shù)地址。

6.2.1通過寄存器傳遞

這種傳遞方式使用方便,適用于參數(shù)較少的

情況。

例1.把BX中的16位二進制數(shù)轉(zhuǎn)換成

十進制并顯示在屏幕上。

程序6.3

STASGSEGMENT

DW32DUP(?)

STASGENDS

CODESEGMENT

ASSUMECS:CODE

MAINPROCFAR

MOVBX,162EH

CALLTERN

MOVAX,4C00H

INT21H

MAINENDP

PROC;二一十并顯示。

MOVCX,10000

CALLDEC_DIV;轉(zhuǎn)換萬位數(shù)

MOVCX,1000

CALLDEC_DIV;轉(zhuǎn)換千位數(shù)

MOVCX,100

CALLDEC_DIV;轉(zhuǎn)換百位數(shù)

MOVCX,10

CALLDEC_DIV;轉(zhuǎn)換十位數(shù)

MOVCX,1

CALLDEC_DIV;轉(zhuǎn)換個位數(shù)

RET

TERNENDP

PROC;ex中為十進制的位權(quán)

MOVAX,BX

MOVDX,0

DIVCX;商為轉(zhuǎn)換后的一位十進制數(shù)

MOVBX,DX

MOVDL,AL

ADDDL,30H;轉(zhuǎn)換成ASCII碼

MOVAH,2;顯示

INT21H

RET

DEC.DIVENDP

CODEENDS

ENDMAIN」

6^2同模塊中的子程序可直接訪問模塊中的變量

若調(diào)用程序和子程序在同模塊中,子程序

可以直接訪問模塊中的變量。

例2.實現(xiàn)數(shù)組求和功能。要求數(shù)組求

和(不考慮溢出情況)由子程序?qū)崿F(xiàn),其數(shù)

組元素及結(jié)果均為字型數(shù)據(jù)。見程序6.4。

STACKSGSEGMENTSTACK'STK,

DW32DUP('S')

STACKSGENDS

DATASEGMENT

ARYDW1,2,3,4,5,6,7,8,9,10

COUNTDW($-ARY)/2;數(shù)組元素個數(shù)

SUMDW?;數(shù)組和的地址

DATAENDS

C0DE1SEGMENT

學TIAINPROCFAR

ASSUMECS:CODE1,DS:DATA

PUSHDS

XORAX,AX

PUSHAX

MOVAX,DATA

MOVDS,AX

CALLFARPTRARY_SUM

RET

MAINENDP

C0DE1ENDS

C0DE2SEGMENT

ASSUMECS:C0DE2

ARY_SUMPROCFAR;數(shù)組求和子程序

PUSHAX;保存寄存器

PUSHCX

PUSHSI

LEASI,ARY;取數(shù)組起始地址

MOVCX,COUNT;取元素個數(shù)

XORAX,AX;清0累加器

ADDAX,[SI];累加和

ADDSI,TYPEARY;修改地址指針

LOOPNEXT

MOVSUM,AX;存和

POPSI;恢復寄存器

POPCX

POPAX

RET

ARY_SUMENDP

C0DE2ENDS

ENDMAIN

*

6.堂通過地址表傳遞參數(shù)地址

?適用于參數(shù)較多的情況。具體方法是先建立一個

地址表,該表由參數(shù)地址構(gòu)成。然后把表的首地址通過

寄存器或堆棧傳遞給子程序。

例3.編寫一個數(shù)組求和子程序,

其數(shù)組元素及結(jié)果均為字型數(shù)據(jù)。另

定義兩個數(shù)組,并編寫一個主程序,

通過調(diào)用數(shù)組求和子程序分別求出兩

個數(shù)組的和。見程序6.5。

程序6.5

KSGSEGMENTSTACK'STK,

STACKSGENDS

DATASEGMENT

;數(shù)組1

COUNTDW($-ARY)/2;數(shù)組1的元素個數(shù)

SUM;數(shù)組1的和地址

NUM10,20,30,40,50;數(shù)組2

($-NUM)/2;數(shù)組2的元素個數(shù)

TOTAL;數(shù)組2的和地址

TABLEDW3DUP(?);地址表

DATAENDS

,0DE1SEGMENT

#+KPROCFAR

J---

ASSUMECS:CODE1,DS:DATA

PUSHDS

XORAX,AX

PUSHAX

MOVAX,DATA

MOVDS,AX;構(gòu)造數(shù)組1的地址表

MOVTABLE,OFFSETARY

MOVTABLE+2,OFFSETCOUNT

MOVTABLE+4,OFFSETSUM

LEABX,TABLE;傳遞地址表首地址

CALLFARPTRARY_SUM,

二;構(gòu)造數(shù)組2的地址表

MOVTABLE,OFFSETNUM

MOVTABLE+2,OFFSETCT

MOVTABLE+4,OFFSETTOTAL

LEABX,TABLE

;傳遞地址表的首地址

CALLFARPTRARY_SUM

;段間調(diào)用調(diào)用數(shù)組求和子程序

RET

MAINENDP

CODE1ENDS

SEGMENT

ASSUMECS:C0DE2

ARY_SUMPROCFAR;數(shù)組求和子程序

PUSHAX;保存寄存器

PUSHCX

PUSHSI

PUSHDI

MOVSI,[BX]取數(shù)組起始地址

MOVDI,[BX+2]取元素個數(shù)地址

MOVCX,[DI]取元素個數(shù)

MOVDI,[BX+4]取結(jié)果地址

XORAX,AX清0累加器,

ADDAX,[SI];累加和

ADDSI,TYPEARY;修改地址指針

LOOPNEXT

MOV[DI],AX;存和

POPDI;恢復寄存器

POPSI

POPCX

POPAX

RET

ARY_SUMENDP

C0DE2ENDS

ENDMAIN

6,他通過堆棧傳遞參數(shù)或參數(shù)地址

這種方式適用于參數(shù)較多,或子程序有多層

嵌套、遞歸調(diào)用的情況。

步驟:

?主程序把參數(shù)或參數(shù)地址壓入堆棧;

?子程序使用堆棧中的參數(shù)或通過棧中參數(shù)地址取到參數(shù);

?子程序返回時使用RETn指令調(diào)整SP指針,以便刪除堆棧中已用過

的參數(shù),保持堆棧平衡,保證程序的正確返回。

麻完成數(shù)組求和功能,求和由子程序?qū)?/p>

現(xiàn),:要求通過堆棧傳遞參數(shù)地址。

程序6.6

STACKSGSEGMENTSTACK'STK,

DW16DUP(?)

STACKSGENDS

DATASEGMENT

ARYDW1,2,3,4,5,6,7,8,9,10

COUNTDW($-ARY)/2

SUMDW?

DATAENDS

C0DE1SEGMENT

MAINPROCFAR

ASSUMECS:CODE1,DS:DATA

PUSHDS{)

XORAX,AX

PUSHAX;⑵

MOVAX,DATA

MOVDS,AX

LEABX,ARY

PUSHBX;⑶壓入數(shù)組起始地址

LEABX,COUNT

PUSHBX;⑷壓入元素個數(shù)地址

LEABX,SUM

PUSHBX;(5)壓入和地址

CALLFARPTRARYSUM

"6)調(diào)用求和子程序

MAINENDP

CODE1ENDS

SEGMENT

ASSUMECS:C0DE2

ARYSUMPROCFAR數(shù)組求和子程序

PUSHBP⑺保存BP值

MOVBP,SPBP是堆棧數(shù)據(jù)的地址指針

PUSHAX⑻保存寄存器內(nèi)容

PUSHCX(9)

PUSHSI10

PUSHDI(11)

MOVSI,[BP+1O1得到數(shù)組起始地址

MOVDI,[BP+8]得到元素個數(shù)地址

MOVCX,DI得到元素個數(shù)

MOVDI,LBP+6J得到和地址

XORAX,AX

ADDAX,[SI];累加

ADDSI,TYPEARY;修改地址指針

LOOPNEXT

MOV[DI],AX存和

POPDI?恢復寄存器內(nèi)容

POPSI(13)

POPCX(14)

POPAX(15)

POPBP(16)

RET6?返回并調(diào)整SP指針

ARY_SUMENDP

C0DE2ENDS

ENDMAIN

DI值語句(11)執(zhí)行后堆棧狀態(tài)

SI值語句⑩執(zhí)行后堆棧狀態(tài)

CX值語句⑼執(zhí)行后堆棧狀態(tài)

AX值語句⑻執(zhí)行后堆棧狀態(tài)

BPABP值語句⑺執(zhí)行后堆棧狀態(tài)

IP值語句⑹執(zhí)行后堆棧狀態(tài)

CS值

SUM的地址語句⑸執(zhí)行后堆棧狀態(tài)

COUNT地址語句⑷執(zhí)行后堆棧狀態(tài)

ARY首地址語句⑶執(zhí)行后堆棧狀態(tài)

0語句⑵執(zhí)行后堆棧狀態(tài)

PSP段基址語句⑴執(zhí)行后堆棧狀態(tài)

程序6.6中所有入棧操作對堆棧的影響

DI值

SI值

CX值

AX值

BP值

IP值

CS值

SUM的地址

COUNT地址

ARY首地址

0語句(17)執(zhí)行后堆棧狀態(tài)

PSP段基址

程序6.6中主程序的RET執(zhí)行前堆棧狀態(tài)

例5.完成數(shù)組求和功能,其中

由子程序?qū)崿F(xiàn),要求使用結(jié)構(gòu)

編碼見程序6.7。

堆棧數(shù)據(jù)結(jié)構(gòu)字段名

DI值

SI值

CX值

AX值

BP值SAVE_BP'

IP值SAVE_CS_IP

CS值

SUM的地址SUM_ADDR吆吉構(gòu)

COUNT地址COUNT_ADDR

ARY首地址ARYADDR,

0

PSP段基址

程序6.7的堆棧及結(jié)構(gòu)數(shù)據(jù)示意圖i反

程序6.7

STACKSGSEGMENTSTACK'STK'

DW16DUP('S')

STACKSGENDS

DATASEGMENT

ARYDW1,2,3,4,5,6,7,8,9,10

COUNTDW($-ARY)/2

SUMDW?

DATAENDS

CODE1SEGMENT

MAINPROCFAR

ASSUMECS:CODE1,DS:DATA

PUSHDS

XORAX,AX

PUSHAX

MOVAX,DATA

MOVDS,AX

LEABX,ARY

PUSHBX;壓入數(shù)組起始地址

LEABX,COUNT

PUSHBX;壓入元素個數(shù)地址

LEABX,SUM

PUSHBX;壓入和地址

CALLFARPTRARYSUM

MAINENDP

CODE1ENDS

C0DE2SEGMENT

ASSUMECS:C0DE2

STACK_STRCSTRUG;定義結(jié)構(gòu)

SAVE_BPDW

SAVE_CS_IPDW2DUP(?)

SUM_ADDRDW?

COUNT_ADDRDW?

ARY_ADDRDW?

STACK_STRCENDS、

HSRY_SUMPROCFAR;數(shù)組求和子程序

PUSHBP;保存BP值

MOVBP,SP

PUSHAX

PUSHCX

PUSHSI

PUSHDI

MOVSI,[BP].ARY_ADDR;數(shù)組文臺地址

MOVDI,[BP].COUNT_ADDR

MOVCX,[DI]

MOVDI,[BP],SUM_ADDR;得至ij和地址

XORAX,AX

L^IEXT:ADDAX,[SI];累加

冬>ADDSI,TYPEARY;修改地址指針

?LOOPNEXT

MOV[DI],AX;存和

POPDI

POPSI

POPCX

POPAX

POPBP

RET6;返回并調(diào)整SP指針

ARY_SUMENDP

C0DE2ENDS

ENDMAIN上

r*.6.3嵌套與遞歸子程序

*1.子程序嵌套

主程序SUB1SUB2

子程序嵌套示意圖返回

2.遞歸子程序

以下是求N!遞歸過程的描述。編碼見程

序6.8。

BE&iN,FACT(N,RESULT)

SAVEREGISTERONSTACK

IFN=O

RESULT-1

ELSE

PUSHADDRESSOFRESULTONTOSTACK

PUSHN-1ONTOSTACK

CALLFACT(N-1,RESULT)

RESULT-N*RESULT

ENDIF

RESTOREREGISTERSFROMSTACK

DELETEPARAMETERSFROMSTACK

莓>程序6.8

STACKSGSEGMENTSTACK'S';定義堆棧

DW128DUP('ST')

STACKSGENDS

DATASEGMENT

N_VALDW3;定義N值

RESULTDW?;結(jié)果

DATAENDS

CODESEGMENT

ASSUMECS:CODE,DS:DATA,SS:STACKSG

FRAMESTRUG;定義幀結(jié)構(gòu)

SAV_BPDW?:保存BP值

SAV_CS_IPDW2DUP(?);保存返回地址

NDW?;當前N值

RESULT_ADDRDW?;結(jié)果地址

FRAMEENDS

PROCFAR

MOVAX,DATA

MOVDS,AX

LEABX,RESULT

PUSHBX;結(jié)果地址入棧

PUSHN_VAL;N值入棧

CALLFARPTRFACT

;調(diào)用遞歸子程序

R1:MOVAX,4C00H

INT21H

MAINENDP

PROCFAR;N!遞歸子程序

PUSHBP;保存BP值

MOVBP,SP;BP指向幀基地址

PUSHBX

PUSHAX

MOVBX,[BP].RESULTADDR

MOVAX,[BP].N;取幀中N值

CMPAX,0

JEDONE;N=O時退出子程序嵌套

PUSHBX;為下一次調(diào)用壓入結(jié)果地址

DECAX

PUSHAX;為下一次調(diào)用壓入(N—1)值

CALLFARPTRFACT

MOVBX,[BP].RESULT_ADDR

MOVAX,[BX];取中間結(jié)果(N—1)!

MUL[BP].N;N*(N-1)!

JMPSHORTRETURN

DONE:MOVAX,1;O!=1

RETURN:MOV[BX],AX;存中間結(jié)果

POPAX

POPBX

POPBP

RET4

FACTENDP

CODEENDS

ENDMAIN/

程序6.8的運行情況:

①主程序把結(jié)果地址和N的初始值壓

入堆棧,然后調(diào)用FACT子程序。

②在FACT中,它不斷調(diào)用自身,每調(diào)

用一次都要在堆棧中形成一幀,該幀由以

下信息組成:子程序中要用到的寄存器內(nèi)

容、中間結(jié)果地址、(N-1)的值、子程

序返回地址,自身調(diào)用直到N=0為止。

③當N=0時開始返回。

④通過[BP].RESULT_ADDR和[BP].N取

出堆棧中本次使用的參數(shù),計算N*(N-

1)!的值,保存中間結(jié)果,恢復寄存器的

爭,用RET4返回并廢除已用過的N和中

間結(jié)果地址。

⑤重復第④步,逐層返回直到N等

于初始值為止。

嗨-6.4.1宏定義、宏調(diào)用、宏擴展

宏指令是源程序中一段有獨立功

能的程序代碼。宏指令由宏定義偽指

令定義,它只需在源程序中定義一次

,便可以多次被調(diào)用。

★宏定義偽指令格式:

宏指令名MACRO[形式參數(shù)表]

...;宏指令體

ENDM

例1.輸入一個字符的宏定義、宏調(diào)用、宏擴展

INCHARMACRO

MOVAH,1

INT21H;輸入的字符在AL

ENDM

;宏調(diào)用

INCHAR

當匯編程序匯編到宏指令INCHAR時,則對其擴

展如下:

1MOVAH,1

1INT21H

指令前的“1”表示該語句是擴展時替換

得到的。

f1一

,嗎J設計宏指令時應注意的問題

由于宏指令也像子程序那樣可以被多次

調(diào)用或被多個程序共享,所以在設計時需要

注意以下問題:

1.宏指令說明

2.寄存器的保存與恢復

3.宏指令中的符號說明

整」6.4.2LOCAL偽指令

格式:LOCAL局部符號表

功能:對局部符號表中的每個符號,在匯編時每

擴展一次便建立一個惟一的符號,形如??XXXX(

xxxx的值在0000孑FFF之間)。以保證匯編時生成名字的

惟一性。

尸繁例2.以下是定義一個延時程序的宏指令delay,并且在同

值—一個程序中兩次被調(diào)用的擴展情況。

;宏定義

DELAYMACRO

LOCALLOP

MOVCX,2801

LOP:LOOPLOP

ENDM

宏調(diào)用:

^^WJELAY

DELAY

匯編時宏擴展如下:

DELAY

0009B90AF1■IMOVCX,2801

ooocE2FE1??0000:LOOP??0000

DELAY

OOOEB90AF11MOVCX,2801

0011E2FE1??0001:LOOP??000

瑞?宏指令中參數(shù)的使用

在宏定義時可以帶有形式參數(shù),而在宏

調(diào)用時給出實參數(shù)即可。

宏指令的參數(shù)可以是常數(shù)、寄存器、變

量、表達式、操作碼或操作碼的一部分、指

令或偽指令助記符等。

例3.定義在兩個字型內(nèi)存變量之間傳送數(shù)據(jù)的宏

指令,并調(diào)用它,然后觀察其擴展情況。

MOVEMOCROX,Y

PUSHAX

MOVAX,X

MOVY,AX

POPAX

ENDM

SEGMENT

VAR1DW6543H

VAR2

DATAENDS

;右調(diào)用;右擴展

MOVEVAR1,VAR2iPUSHAX

1MOVAX,VAR1

1MOVVAR2,AX

1POPAX

飛j643宏指令嵌套

宏指令嵌套有兩種情況:

.宏定義體中含有宏調(diào)用

?宏定義體中含有宏定義

例14.宏定義體中嵌套宏定義的宏指令、宏調(diào)用及宏擴展示例。

DMACMACROMNAME,OPER;外層宏定義

MNAMEMACROX,Y,Z;內(nèi)層宏定義

PUSHAX

MOVAX,X

OPERAX,Y

MOVZ,AX

POPAX

ENDM

ENDM

DW25

逐jDW12

YDW9

??

DMACADDITION,ADD;外層宏調(diào)用

1ADDITIONMACROX,Y,Z

1PUSHAX

1MOVAX,X

ADDAX,Y

MOVZ,AX

POPAX

ENDM

ADDITIONA,B,C;內(nèi)層右調(diào)用

1PUSHAX

1MOVAX,A

1ADDAX,B

1MOVC,AX

1POPAX

DMACLOGIC_AND,AND;外層宏調(diào)用

1LOGIC_ANDMACROX,Y,Z

1PUSHAX

1MOVAX,X

1ANDAX,Y

1MOVZ,AX

1POPAX

1ENDM

FLDGICANDA,B,C;內(nèi)層右調(diào)用

IPUSHAX

1MOVAX,A

1ANDAX,B

1MOVC,AX

1POPAX

使用適當?shù)膶崊?shù),通過調(diào)用DMAC宏指令可

以生成另一條新的宏指令,再調(diào)用新宏指令可

以實現(xiàn)任何雙操作數(shù)指令的操作,而且兩個操

作數(shù)可以同時為存儲器操作數(shù)。這種方法使

宏的功能更強大。

■/URGE偽指令

格式:PURGE宏指令名....

功能:從內(nèi)存中刪除指定的宏指令

例:

PURGEINCHAR

6.4.4宏操作符

這些操作符不僅適用于宏指令,也適用于

重復匯編偽指令。

宏操作符格式名稱

&參數(shù)文本替換操作符

<字符串〉文本原樣傳遞操作符

!字符字符原意操作符

%表達式表達式操作符

"注釋宏注釋

1.操作符&

在宏定義體中&可以作為形式參數(shù)的前綴,而當宏擴展

時則把&前后兩個符號合并形成一個符號,這個符號可以是操

作碼、操作數(shù)或是一個字符串。

例5.下面定義的PutData宏指令中,參數(shù)TheName作為

變量名的一部分,通過&把前后兩個符號合并成一個變量名。

在Ju叩宏指令中,參數(shù)Cond作為操作碼的一部分,通過&把前

后兩個符號合并成一個指令助記符。

⑴PUTDATA宏指令

PUTDATAMACROTHENAME,THEDATA

PD&THENAMEDBTHEDATA

ENDM

;宏調(diào)用

PUTDATAMYDATA,5

;宏擴展

1PDMYDATADB5

⑵JUMP宏指令

JUMPMACROCOND,L

J&CONDL

ENDM

;宏調(diào)用

JUMPNE,LAB1

;宏擴展

1JNELAB1

二在宏指令中,當使用&操作符生成的是

一個變量名或標號時,同樣要注意在一個程

序中多次調(diào)用同一個宏指令時出現(xiàn)的符號重

定義錯誤。若有這種可能性,應把名字用

LOCAL偽指令說明成局部的。如下所示:

;宏定義

PUTDATAOMACROTHENAME,THEDATA

LOCALPD_&THENAME

PD_&THENAMEDBTHEDATA

ENDM

;宏調(diào)用

PUTDATAOMYDATA,5

;宏擴展

1??OOOOMYDATADB5

;宏調(diào)用

PUTDATAOMYDATA,8

;宏擴展

1??OOO1MYDATADB8

返叵

2.文本原樣傳遞操作符<>

嗎血9>操作符括起的內(nèi)容作為一個整體原樣傳遞。

力U如,可以使用<>符號包圍目標,從而使該目標作為單

一的參數(shù)而不是多個參數(shù)的列表。

例6.用不同的實參數(shù)調(diào)用PUTDATA宏指令,觀察它們的變化。

PUTDATAMACROTHENAME,THEDATA

PD_&THENAMEDBTHEDATA

ENDM

;宏調(diào)用1

PUTDATAMYDATA,5,4,3

;宏擴展

1PD_MYDATADB5

;宏調(diào)用2

PUTDATAMYDATA,<5,4,3>

;宏擴展

1PD_MYDATADB5,4,3

Numeric=10+2

TextuaIequ<10+2>

其匯編結(jié)果是:

NUMERIC.................NUMBER000C

TEXTUAL................TEXT10+2

可以看到,對Numeric已經(jīng)求值,而

TextuaI只是一串字符而已。一

y■■..

駕字符原意操作符!

!操作符指示MASM把后跟的一個字符原樣傳送

,即把它只作為普通字符對待。

例如,若你需要把“!&>%”符號中的一個作為

宏指令中的字符,可以使用!操作符。

例7.以下宏調(diào)用的第二個實參數(shù)是一串警告信息,其中最

符希望是感嘆號“!”。但“!”是宏操作符,要想把

當做其原意感嘆號對待,就需在它前邊加上宏操作符!。

;宏定義

DEBUGMSGMACROPOINT,STRING

MSG&POINTDB,ATPOINT&POINT:&STRING,

;宏調(diào)用,其中第一個!為宏操作符,第二個??;是感嘆號

DEBUGMSG6,<INSERTIONFAILS!!>

;宏擴展

1MSG6DB'ATPOINT6:INSERTIONFAILS!'

4.表達式操作符%

j在宏調(diào)用時,%操作符強迫后跟的表達式立即求值,并

把表達式的結(jié)果作為實參數(shù)替換,而不是表達式本身。

例8.定義Probleml宏指令,并比較兩次調(diào)用Problend

宏指令的區(qū)別,其中一次調(diào)用中使用了%操作符。

Probleml宏指令功能:把由宏指令參數(shù)所指定的字型數(shù)

組(array)的一個元素裝入AX寄存器,該參數(shù)經(jīng)匯編后必須

是一個常數(shù)表達式。

MACROPARAMETER

MOVAX,ARRAY[PARAMETER*2]

ENDM

;宏調(diào)用L希望取出ARRAY】2,其中的參數(shù)〃10+2〃是表達式本身

PR0BLEM110+2

宏擴展L1MOVAX,ARRAY[10+2*2]

實際取出的是ARRAY,,正確的表達是:

宏調(diào)用2:PR0BLEM1%10+2

宏擴展2:1MOVAX,ARRAY[12*2]

注意:由于MASM在調(diào)用宏指令時對

其中的參數(shù)經(jīng)常是原文替換,所以有時

產(chǎn)生的可能不是預期的結(jié)果。

考慮以下對PR0BLEM1的宏調(diào)用及宏擴展:

;宏調(diào)用,要求裝入ARRAY的元素2

PR0BLEM12

;宏擴展

1MOVAX,ARRAY[2*2]

可以看到,宏擴展后結(jié)果正確。

廣宏調(diào)用:裝入ARRAY的元素10:

INDEX=8

PR0BLEM1INDEX+2

;宏擴展

1MOVAX,ARRAY[INDEX+2*2]

因為MASM的地址表達式遵守操作符優(yōu)先

級的優(yōu)先規(guī)則,則該語句宏擴展后不是預想

的結(jié)果,它訪問的是元素6(索引12),而

不是元素10(索引20)。

貨為了能夠得到正確的結(jié)果,可以在宏指

令的參數(shù)表達式中用()把參數(shù)括起來:

;曉義

PR0BLEM2MACROPARAMETER

MOVAX,ARRAY[(PARAMETER)*2]

ENDM

;宏調(diào)用

INDEX=8

PR0BLEM2INDEX+2

;宏擴展

1MOVAX,ARRAY[(INDEX+2)*2]

心.宏注釋;;

在宏定義中,若注釋以一個分號開始

,則該注釋在宏擴展時出現(xiàn)。但若注釋以

兩個分號開始,則該注釋在宏擴展時不出

現(xiàn)。舉例見列表偽指令。

返回

6.4.5列表偽指令

格式功能

.LALL在列表文件中列出全部宏文本內(nèi)容

(以雙分號開頭的注釋除外)

.SALL在列表文件中不顯示任何宏文本內(nèi)容

,XALL(缺?。┰诹斜砦募兄涣谐隹僧a(chǎn)生

目標代碼的宏文本內(nèi)容

注意:這些列表偽指令只影響列表文件,并

不影響目標碼萌生成。一

6.5宏指令庫

為了使宏指令能讓多個程序共享,可以把它們

組織到一個文件中,并存放在磁盤上,把這種文件稱

為宏指令庫。

1.建立宏指令庫

可以把一些常用的宏指令集中在一個文件中形

成宏指令庫,用EDIT等任何文本編輯程序創(chuàng)建宏指令

庫,庫名由用戶自己起,而且對庫的擴展名沒有特殊

要求。庫中的宏指令以源代碼形式出現(xiàn)。

假設MACRO.LIB中包含以下宏指令(詳細內(nèi)容

見教材P174):

SETMODE;設置80*25彩色顯示模式

INCHAR;接收一個字符,并返回在AL中

OUTCHARX;輸出X字符

PUSHREG;保存寄存器DX、CX、BX、AX、DI、SI、BP

POPREG;恢復寄存器BP、SI、DI、AX、BX、CX、DX

WINDOWMACRO

Collor,WleftTopRow,WLeftTopCul,

WRightBottomRow,WRightBottomCuI

;功能:開窗口

MOVEMOCROX,Y;字型數(shù)據(jù)X送Y變量

CLRSCRN;清屏

CURSOR;置光標,入口參數(shù):口出口1_=行,列號

RETURN;返回操作系統(tǒng)

BIN_DECMACROASC,BlN

;功能:把16位二進制數(shù)轉(zhuǎn)換為十進制數(shù)的

;ASCII值,ASC為5個字節(jié)的十進制數(shù)緩沖區(qū)

;BIN為要轉(zhuǎn)換的二進制數(shù)。

DISPMACROASC

;顯示首址為ASC的字符串

2.把宏指令庫包含到應用程序中

格式:INCLUDE源文件名

功能:把另一個源文件包含到當前源文件中。

3.使用宏指令庫中的宏指令

例9.實現(xiàn)32位二進制數(shù)除以16位二進制數(shù),

并把結(jié)果用十進制數(shù)形式顯示在屏幕上。

編碼見程序6.9o

程序6.9

INCLUDEMACRO.LIB

PURGESETMODE,INCHAR,OUTCHAR,

WINDOW,MOVE,MUL

STACKSGSEGMENT

STACKSGENDS

DATASEGMENT

ADD7006652被除數(shù)

BDW1234除數(shù)

CDWQ商

PROMPTDB

ASCIIDB;轉(zhuǎn)換結(jié)果

DATAENDS

CODESEGMENT

ASSUME

CS:CODE,DS:DATA,SS:STACKSG

MAINPROCFAR

MOVAX,DATA

MOVDX,WORDPTRA+2

MOVAX,WORDPTRA

BIN_DECASCII,AX

CLRSCRN

DISPPROMPT

DISPASCII

RETURN

MAINENDP

CODEENDS

ENDMAIN

■-4.宏指令與子程序的區(qū)別

采用宏和子程序均能達到代碼共

享、簡化源程序的目的,但它們的區(qū)

別也是顯而易見的。區(qū)別主要有以下

幾點:

CT?工作方式的區(qū)別

(2)參數(shù)傳遞的方便性

(3)參數(shù)的多樣性及靈活性

通常:

?宏指令被用在代碼較短且參數(shù)

較多的場合;

?子程序被用在代碼較長的場合O

*6.6重復偽指令

當程序中需要重復書寫相同或幾乎相

同的語句時,可以用重復偽指令定義重復

塊,以簡化程序和減輕程序設計人員的工

作量。絕大部分MASM版本提供了REPT、

IRP和IRPC重復偽指令,而在MASM6.X中還

提供了其它重復偽指令。

6.6.1重復偽指令REPT

格式:

REPT

;重復塊

ENDM

匯編程序使重復塊的內(nèi)容重復多

次,重復次數(shù)由表達式給出。

說明:重復塊中可以出現(xiàn)任何有效的匯

編語句,數(shù)值表達式的計算結(jié)果應該是無符

號常數(shù)。

DATASEGMENT

TABLELABELWORD

REPT6;重復6次

DWX*X*X;定義立方值

X=X+1

ENDM

DATAENDS

匯編后的情況如下:

(1)0000DATASEGMENT

(2)0000TABLELABELWORD

(3)=0005X=5

REPT6

DWX*X*X

X=X+1

⑺ENDM

(8)0000007D1X*X*X

(9)000200D81X*X*X

(10)000401571X*X*X

(11)000602001X*X*X

(12)000802D91X*X*X

(13)000A03E81X*X*X

(14)000CDATAENDS

第(8)到第(13)行是匯編后的情況。在

MOVBX,10

REPT2

DECBX

ENDM

匯編后產(chǎn)生如下語句:

MOVBX,10

1DECBX

1DECBX

CHARSMACRONUM

MOVAH,2

CHAR='A'

REPTNUM

MOVDL,CHAR

INT21H

CHAR=CHAR+1

ENDM

ENDM

CODESEGMENT

ASSUMECS:CODE

MAINPROCFAR

CHARS26

MOVAX,4C00H

INT21H

MAINENDP

CODEENDS

ENDMAIN

從本例可以看出,重復偽指令可

以出現(xiàn)在宏指令中。

CHARSMACRONUM

MOVAH,2

CHAR='A'

REPTNUM

MOVDL,CHAR

INT21H

CHAR=CHAR+1

ENDM

ENDM

CODESEGMENT

ASSUMECS:CODE

OOOOMAINPROCFAR

CHARS26

0000B4021MOVAH,2

0002B2412MOVDL,CHAR;字符A

0004CD212INT21H

0006B2422MOVDL,CHAR;字符B

0008CD212INT21H

0066MOVDL,CHAR;字符Z

0068INT21H

006AB84C00AX,4C00H

006DINT21H

006FMAINENDP

006FCODEENDS

MAIN

IT:6.6.2不定重復偽指令

BRP偽指令

格式:

IRP形式參數(shù),(實參數(shù)〉

...;重復塊

ENDM

功能:匯編程序使重復塊的內(nèi)容重復多

次,重復次數(shù)由實參數(shù)個數(shù)決定。每次重復

都用尖括號中的一個實參數(shù)替代形式參數(shù),

依次使用實參數(shù),直到用完為止。

1.實參數(shù)可以是符號。

IRPREG,<AX,BX,CX,DX>

PUSHREG

ENDM

匯編后產(chǎn)生以下指令:

1PUSHAX

1PUSHBX

1PUSHCX

1PUSHDX

X,<1,2,3+5,'EDIT'》

DBX

ENDM

匯編后產(chǎn)生的,LST文件:

0000011DB1;數(shù)字

0001021DB2;數(shù)字

0002081DB3+5;常數(shù)表達式

0003454449541DB、EDI「;ASCII值

從目標碼部分可以看出,數(shù)字1、2生成01

、02,3+5計算后其值為8,,EDI「生成相應的

ASCII值45、44、49、54。

2.IRPC偽指令

冬格式:

IRPC形式參數(shù),數(shù)字串

;重復塊

ENDM

功能:匯編程序使重復塊的內(nèi)容重復多

次,重復次數(shù)由數(shù)字串中數(shù)字位數(shù)決定。每

次重復都用數(shù)字串中一個數(shù)字替代形參,依

次使用串中的數(shù)字,直到用完為止。

說明:重復塊中可以出現(xiàn)任何有效的匯

編語句。

,二例2.定義一串數(shù)字。

!RPCZ,1235

DBZ

ENDM

匯編后生成的.LST文件如下:

0001011DB1

0002021DB2

溫馨提示

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

評論

0/150

提交評論