第4章2匯編語(yǔ)言子程序與宏指令設(shè)計(jì)_第1頁(yè)
第4章2匯編語(yǔ)言子程序與宏指令設(shè)計(jì)_第2頁(yè)
第4章2匯編語(yǔ)言子程序與宏指令設(shè)計(jì)_第3頁(yè)
第4章2匯編語(yǔ)言子程序與宏指令設(shè)計(jì)_第4頁(yè)
第4章2匯編語(yǔ)言子程序與宏指令設(shè)計(jì)_第5頁(yè)
已閱讀5頁(yè),還剩127頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第4章_2子程序與宏指令設(shè)計(jì)

子程序?yàn)楸阌谀K化程序設(shè)計(jì)和程序共享,經(jīng)常把一些相對(duì)獨(dú)立的程序段組織成子程序的形式;當(dāng)需要實(shí)現(xiàn)該子程序功能時(shí),由調(diào)用程序(或稱為主程序)調(diào)用之,當(dāng)子程序結(jié)束后再返回到主程序繼續(xù)執(zhí)行。

主程序子程序

主子程序關(guān)系示意圖①②③④在匯編語(yǔ)言中用過(guò)程定義偽指令定義子程序。過(guò)程定義偽指令格式: 過(guò)程名 PROC屬性

過(guò)程名 ENDP4.1子程序結(jié)構(gòu)說(shuō)明:過(guò)程名由用戶自己起。過(guò)程名是子程序入口的符號(hào)地址。類型選項(xiàng)指明該過(guò)程的類型,可以是:

NEAR(或缺?。f(shuō)明該過(guò)程是近型的,只能在段內(nèi)被調(diào)用

FAR

—說(shuō)明該過(guò)程是遠(yuǎn)型的,可以在段間被調(diào)用,也可以在段內(nèi)被調(diào)用。含有子程序的程序結(jié)構(gòu)

1.調(diào)用程序和子程序在同一個(gè)代碼段的程序結(jié)構(gòu)(子程序類型可缺?。?/p>

CODE SEGMENT MAIN PROC FAR LEABX,TABLE;傳遞地址表首地址 TTT: CALL SUB1 DISTURB: MOVAX,DX … RET MAIN ENDP

SUB1 PROC … RET SUB1 ENDP CODE ENDS END MAIN2.調(diào)用程序和子程序在不同代碼段的程序結(jié)構(gòu)

(SUB2既被段間調(diào)用又被段內(nèi)調(diào)用,必須是FAR屬性。

CALL要顯式說(shuō)明是FAR屬性)

CODE1 SEGMENT

MAIN PROC FAR …

CALL FARPTRSUB2 … RET MAIN ENDP CODE1 ENDS

CODE2 SEGMENT SUB1 PROC FAR … CALL FARPTRSUB2 … RET SUB1 ENDP

SUB2 PROC FAR … RET SUB2 ENDP CODE2 ENDS END MAIN4.2子程序的調(diào)用和返回1.段內(nèi)調(diào)用:調(diào)用程序和子程序在同一個(gè)代碼段的程序結(jié)構(gòu)2.段間調(diào)用:調(diào)用程序和子程序在不同代碼段的程序結(jié)構(gòu)1.子程序調(diào)用指令CALL

格式:CALLDST

功能:調(diào)用子程序。 說(shuō)明:DST為子程序名或子程序入口地址.執(zhí)行時(shí)先把返回地址(斷點(diǎn))壓入堆棧,再形成子程序入口地址,把控制權(quán)交給子程序。 ⑴段內(nèi)調(diào)用調(diào)用指令實(shí)現(xiàn)同一段內(nèi)的子程序調(diào)用,調(diào)用時(shí)只改變IP值,不改變CS值。

執(zhí)行操作: 把返回地址(CALL之后的那條指令地址的偏移量部分(當(dāng)前IP值))壓入堆棧。 根據(jù)與轉(zhuǎn)移地址有關(guān)的尋址方式形成子程序入口地址的IP值。把控制無(wú)條件轉(zhuǎn)向子程序,即執(zhí)行CS:IP處的指令。①段內(nèi)直接調(diào)用:

格式:CALLPROCEDURE

或:CALLNEARPTRPROCEDURE

功能:調(diào)用PROCEDURE子程序。執(zhí)行時(shí)先把返回地址的偏移量地址壓入堆棧,再使IP=(IP)+disp16,把控制權(quán)交給子程序。

說(shuō)明:這種指令使用與轉(zhuǎn)移地址有關(guān)的尋址方式中的段內(nèi)直接尋址方式。

例1.

設(shè)子程序A與CALL指令在同一段內(nèi),則調(diào)用A子程序的指令是:

CALLA或: CALLNEARPTRA②段內(nèi)間接調(diào)用:

格式:CALLREG/M

功能:調(diào)用子程序。執(zhí)行時(shí)先把返回地址的偏移量地址壓入堆棧;再把指令指定的16位通用寄存器或內(nèi)存單元的內(nèi)容送給IP,把控制權(quán)交給子程序。 說(shuō)明:這種指令使用與轉(zhuǎn)移地址有關(guān)的尋址方式中的段內(nèi)間接尋址方式,指令指定的通用寄存器或內(nèi)存單元中存放段內(nèi)偏移量例2.

可以把子程序入口地址的偏移量送給通用寄存器或內(nèi)存單元,通過(guò)它們實(shí)現(xiàn)段內(nèi)間接調(diào)用。CALLWORDPTRBX;子程序入口地址的偏移量在BX中CALLWORDPTR[BX];子程序入口地址的偏移量在數(shù)據(jù)段的

BX所指向的內(nèi)存單元中CALLWORDPTR[BX][SI];子程序入口地址的偏移量在數(shù)據(jù)段

的BX+SI所指向的內(nèi)存單元中⑵段間調(diào)用這類調(diào)用指令可以實(shí)現(xiàn)段間調(diào)用(FAR型調(diào)用),執(zhí)行時(shí)即要改變IP值,也要改變CS值。①段間直接調(diào)用:

格式:CALLFARPTRPROCEDURE

功能:調(diào)用PROCEDURE子程序。執(zhí)行時(shí)先把返回地址(IP當(dāng)前值和CS當(dāng)前值)壓入堆棧再把PROCEDURE的偏移量部分送給IP,段基址部分送給CS,把控制權(quán)交給子程序。

說(shuō)明:這種指令使用與轉(zhuǎn)移地址有關(guān)的尋址方式中的段間直接尋址方式。

例3.

設(shè)子程序B與CALL指令不在同一段內(nèi),則段間直接調(diào)用B子程序的指令是:

CALLFARPTRB②段間間接調(diào)用:

格式:CALLMEM

功能:調(diào)用子程序。執(zhí)行時(shí)先把返回地址(當(dāng)前IP值和當(dāng)前CS值)壓入堆棧;再把MEM的低字送給IP,高字送給CS,把控制權(quán)交給子程序。 說(shuō)明:這種指令使用與轉(zhuǎn)移地址有關(guān)的尋址方式中的段間間接尋址方式,其中MEM

為內(nèi)存的雙字長(zhǎng)地址指針,低字部分為16位的偏移量,高字部分為段基址。

例4.

對(duì)于例3,若子程序B的入口地址(偏移量和段基址)放在變量VAR中,即可通過(guò)VAR實(shí)現(xiàn)段間間接調(diào)用:

CALLDWORDPTRVAR;從VAR變量中得到子程序B的入口地址實(shí)現(xiàn)調(diào)用變量VAR的地址也可以通過(guò)寄存器間接尋址方式、基址變址尋址方式等存儲(chǔ)器操作數(shù)尋址方式得到。例.CALLDWORDPTR[BX][DI] 保護(hù)模式的子程序調(diào)用比較復(fù)雜,涉及到調(diào)用門、任務(wù)門、任務(wù)狀態(tài)段等知識(shí)。子程序返回指令RET執(zhí)行這組指令可以返回到斷點(diǎn)。有兩條返回指令,它們都不影響標(biāo)志。(1)返回指令RET

格式:RET

功能:

從棧頂彈出返回地址(彈出一個(gè)字到IP)-NEAR型

若子程序是FAR型,(先彈出一個(gè)字到IP,再?gòu)棾鲆粋€(gè)字到CS),返回到主程序繼續(xù)執(zhí)行。 無(wú)論子程序是NEAR型還是FAR型,返回指令的匯編指令格式總是用RET表示。

但經(jīng)匯編后會(huì)產(chǎn)生不同的機(jī)器碼。(2)帶參數(shù)的返回指令

格式:RETimm16

功能:先從棧頂彈出返回地址(彈出一個(gè)字到IP,若子程序是FAR型還需再?gòu)棾鲆粋€(gè)字到CS),后修改棧頂指針SP=(SP)+imm16。

注:其中imm16是16位的立即數(shù),設(shè)通過(guò)堆棧給子程序傳遞了n個(gè)字型參數(shù),則imm16=2n。

修改堆棧指針是為了廢除堆棧中主程序傳遞給子程序的參數(shù)。 以上介紹的子程序返回指令也適用于80X86系列的實(shí)模式環(huán)境,而保護(hù)模式的返回要復(fù)雜些。進(jìn)入子程序后:要保護(hù)主程序的運(yùn)行狀態(tài)(標(biāo)志位的當(dāng)前狀態(tài))主程序中使用的寄存器當(dāng)前內(nèi)容(稱為保護(hù)現(xiàn)場(chǎng)),退出子程序前要恢復(fù)現(xiàn)場(chǎng)。要預(yù)先確定子程序入口參數(shù)和出口參數(shù)。參數(shù)傳遞可利用寄存器、存儲(chǔ)單元或堆棧。4.3設(shè)計(jì)子程序時(shí)應(yīng)注意的問題4.3.1子程序中對(duì)寄存器的保護(hù)與恢復(fù)為什么要保護(hù)寄存器?哪些寄存器要保護(hù)?如何保護(hù)和恢復(fù)?哪些寄存器不能保護(hù)?4.3.2主程序、子程序參數(shù)傳遞常用的參數(shù)傳遞方法如下:1)通過(guò)寄存器傳遞;2)若調(diào)用程序和子程序在同模塊中,子程序可以直接訪問模塊中的變量;3)通過(guò)地址表傳遞參數(shù)地址;4)通過(guò)堆棧傳遞參數(shù)或參數(shù)地址。1通過(guò)寄存器傳遞參數(shù)

這種傳遞方式使用方便,適用于參數(shù)較少的情況。例1.把16位二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制(0~65535)并顯示在屏幕上。

STASG SEGMENT DW32DUP(?)STASG ENDSCODE SEGMENT ASSUMECS:CODEMAIN PROCFAR

MOVBX,162EH

CALLTERN MOVAX,4C00H INT21HMAIN ENDP程序4.3TERN PROC ;二→十轉(zhuǎn)換并顯示

MOVCX,10000 CALLDEC_DIV ;轉(zhuǎn)換萬(wà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)換個(gè)位數(shù)

RETTERN ENDPDEC_DIV PROC ;BX中為待轉(zhuǎn)換的數(shù) ;CX中為十進(jìn)制的位權(quán)

MOVAX,BX MOVDX,0 DIVCX ;商為轉(zhuǎn)換后的一位十進(jìn)制數(shù)

MOVBX,DX;DX中為余數(shù)

MOVDL,AL;AX中為商

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

MOVAH,2 ;顯示

INT21H RETDEC_DIV ENDPCODE ENDS ENDMAIN2同模塊中的子程序可直接訪問模塊中的變量

若調(diào)用程序和子程序在同模塊中,子程序可以直接訪問模塊中的變量。 例2.實(shí)現(xiàn)數(shù)組求和功能。要求數(shù)組求和(不考慮溢出情況)由子程序?qū)崿F(xiàn),其數(shù)組元素及結(jié)果均為字型數(shù)據(jù)。見程序4.4。 STACKSG SEGMENTSTACK'STK‘ DW32DUP('S') STACKSG ENDS DATA SEGMENT ARY DW1,2,3,4,5,6,7,8,9,10 COUNT DW($-ARY)/2 ;數(shù)組元素個(gè)數(shù)

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

DATA ENDS程序4.4

程序4.4數(shù)據(jù)段中定義的變量ARY23456789COUNT11010SUMCODE1 SEGMENTMAIN PROCFAR ASSUMECS:CODE1,DS:DATA …… …… …… MOVAX,DATA MOVDS,AX

CALLFARPTRARY_SUM RETMAIN ENDPCODE1 ENDSCODE2 SEGMENT ASSUMECS:CODE2ARY_SUM PROCFAR

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

PUSHAX ;保護(hù)寄存器內(nèi)容

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

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

XORAX,AX ;清0累加器COUNTARY2345678911010SUMSICX=10NEXT: ADDAX,[SI] ;累加和

ADDSI,TYPEARY ;修改地址指針

LOOPNEXT MOVSUM,AX ;存和

POPSI ;恢復(fù)寄存器

POPCX POPAX RETARY_SUM ENDPCODE2 ENDS ENDMAIN3通過(guò)地址表傳遞參數(shù)地址適用于參數(shù)較多的情況。具體方法:先建立一個(gè)地址表,該表由參數(shù)地址構(gòu)成。然后把地址表的首地址通過(guò)寄存器或堆棧傳遞給子程序例3.編寫一個(gè)數(shù)組求和子程序,其數(shù)組元素及結(jié)果均為字型數(shù)據(jù)。另定義兩個(gè)數(shù)組,并編寫一個(gè)主程序,通過(guò)調(diào)用數(shù)組求和子程序分別求出兩個(gè)數(shù)組的和。見程序4.5。程序4.5STACKSG SEGMENTSTACK'STK' DW32DUP('S')STACKSG ENDSDATA SEGMENTARY DW1,2,3,4,5,6,7,8,9,10 ;數(shù)組1COUNT DW($-ARY)/2 ;數(shù)組1的元素個(gè)數(shù)SUM DW? ;數(shù)組1的和地址NUM DW10,20,30,40,50 ;數(shù)組2CT DW($-NUM)/2 ;數(shù)組2的元素個(gè)數(shù)TOTAL DW? ;數(shù)組2的和地址TABLE DW3DUP(?) ;地址表DATA ENDS

程序4.5數(shù)據(jù)段中定義的變量ARY23456789COUNT11010SUMNUM20304050TOTAL10CT5TABLE CODE1 SEGMENT MAIN PROCFAR ASSUMECS:CODE1,DS:DATA …… MOVAX,DATA MOVDS,AX MOVTABLE,OFFSETARY;構(gòu)造數(shù)組1的地址表

MOVTABLE+2,OFFSETCOUNT MOVTABLE+4,OFFSETSUM LEABX,TABLE ;傳遞地址表首地址

CALLFARPTRARY_SUMARY23456789COUNT11010SUMNUM20304050TOTAL10CT5TABLEARY的偏移量地址COUNT的偏移量地址SUM的偏移量地址BX

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

MOVTABLE+2,OFFSETCTMOVTABLE+4,OFFSETTOTALLEABX,TABLE;傳遞地址表的首地址

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

RETMAINENDPCODE1ENDSCODE2 SEGMENT ASSUMECS:CODE2ARY_SUM PROCFAR ;數(shù)組求和子程序

PUSHAX ;保存寄存器

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

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

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

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

XORAX,AX ;清0累加器COUNTARY2345678911010SUMSICX=10DIDINEXT: ADDAX,[SI] ;累加和

ADDSI,TYPEARY ;修改地址指針

LOOPNEXT MOV[DI],AX ;存和

POPDI ;恢復(fù)寄存器

POPSI POPCX POPAX RETARY_SUM ENDPCODE2 ENDS ENDMAIN

4通過(guò)堆棧傳遞參數(shù)或參數(shù)地址適用于參數(shù)較多,或子程序有多層嵌套、遞歸調(diào)用的情況。步驟:主程序把參數(shù)或參數(shù)地址壓入堆棧;子程序使用堆棧中的參數(shù)或參數(shù)地址取到參數(shù);子程序返回時(shí)使用RETn指令調(diào)整SP指針,

刪除堆棧中已用過(guò)的參數(shù),保持堆棧平衡,保證程序的正確返回。例4.完成數(shù)組求和功能,求和由子程序?qū)崿F(xiàn),要求通過(guò)堆棧傳遞參數(shù)地址。

STACKSG SEGMENTSTACK‘STK’ DW64DUP(?) STACKSG ENDS DATA SEGMENT ARY DW1,2,3,4,5,6,7,8,9,10 COUNT DW($-ARY)/2 SUM DW? DATA ENDS程序4.6

程序4.6數(shù)據(jù)段中定義的變量ARY23456789COUNT11010SUMCODE1 SEGMENTMAIN PROCFAR ASSUMECS:CODE1,DS:DATA PUSH… ;⑴ …… PUSH… ;⑵ MOVAX,DATA MOVDS,AX LEABX,ARY PUSHBX ;⑶壓入數(shù)組起始地址

LEABX,COUNT PUSHBX ;⑷壓入元素個(gè)數(shù)地址

LEABX,SUM PUSHBX ;⑸壓入和地址

CALLFARPTRARY_SUM ;⑹調(diào)用求和子程序DIS: ... RET ;⒅MAIN ENDPCODE1 ENDSCODE2 SEGMENT ASSUMECS:CODE2ARY_SUM PROCFAR ;數(shù)組求和子程序

PUSHBP ;⑺保存BP值

MOVBP,SP ;BP是堆棧數(shù)據(jù)的指針

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

PUSHCX ;⑼ PUSHSI ;⑽ PUSHDI ;⑾ MOVSI,[BP+10] ;得到數(shù)組起始地址

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

MOVCX,[DI] ;得到元素個(gè)數(shù)

MOVDI,[BP+6] ;得到和地址

XORAX,AXCOUNTARY2345678911010SUMSIDIDINEXT: ADDAX,[SI] ;累加

ADDSI,TYPEARY ;修改地址指針

LOOPNEXT MOV[DI],AX ;存和

POPDI ;⑿恢復(fù)寄存器內(nèi)容

POPSI ;⒀ POPCX ;⒁

POPAX ;⒂ POPBP ;⒃ RET6 ;⒄返回并調(diào)整SP指針ARY_SUM ENDPCODE2 ENDS ENDMAIN返回

程序4.6中所有入棧操作對(duì)堆棧的影響語(yǔ)句⑾執(zhí)行后堆棧狀態(tài)語(yǔ)句⑽執(zhí)行后堆棧狀態(tài)語(yǔ)句⑼執(zhí)行后堆棧狀態(tài)語(yǔ)句⑻執(zhí)行后堆棧狀態(tài)語(yǔ)句⑺執(zhí)行后堆棧狀態(tài)語(yǔ)句⑹執(zhí)行后堆棧狀態(tài)

語(yǔ)句⑸執(zhí)行后堆棧狀態(tài)語(yǔ)句⑷執(zhí)行后堆棧狀態(tài)語(yǔ)句⑶執(zhí)行后堆棧狀態(tài)語(yǔ)句⑵執(zhí)行后堆棧狀態(tài)語(yǔ)句⑴執(zhí)行后堆棧狀態(tài)SPBPDI值SI值CX值A(chǔ)X值BP值IP值CS值SUM的偏移量地址COUNT偏移量地址ARY偏移量地址……SP返回

程序4.6中主程序的RET執(zhí)行前堆棧狀態(tài)SP語(yǔ)句⒄?qǐng)?zhí)行后堆棧狀態(tài)SPDI值SI值CX值A(chǔ)X值BP值IP值CS值SUM的地址COUNT地址ARY首地址……語(yǔ)句16執(zhí)行后堆棧狀態(tài)SP語(yǔ)句12執(zhí)行后堆棧狀態(tài)6.4.1宏定義、宏調(diào)用、宏擴(kuò)展宏指令是源程序中一段有獨(dú)立功能的程序代碼。宏指令由宏定義偽指令定義,在源程序中定義一次,可以多次被調(diào)用。

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

;宏指令體

ENDM

★ 宏定義偽指令格式:宏調(diào)用

宏指令一經(jīng)定義,就可以在程序中調(diào)用它,這被稱為宏調(diào)用。

宏調(diào)用格式:宏指令名[實(shí)參數(shù)表]

宏指令與子程序的區(qū)別采用宏和子程序均能達(dá)到代碼共享、簡(jiǎn)化源程序的目的;它們的區(qū)別主要有:(1)工作方式的區(qū)別(2)參數(shù)傳遞的方便性(3)參數(shù)的多樣性及靈活性

通常:宏指令被用在代碼較短且參數(shù)較多的場(chǎng)合;子程序被用在代碼較長(zhǎng)的場(chǎng)合。宏擴(kuò)展

宏擴(kuò)展就是用宏定義體替換宏指令名,

并用實(shí)參數(shù)替換形式參數(shù)。例1.輸入一個(gè)字符的宏定義、宏調(diào)用、宏擴(kuò)展;宏定義INCHAR MACRO MOV AH,1INT 21H ;輸入的字符在AL ENDM;宏調(diào)用

INCHAR當(dāng)匯編程序匯編到宏指令I(lǐng)NCHAR時(shí),則對(duì)其擴(kuò)展如下:

1MOV AH,1 1INT 21H

指令前的“1”表示該語(yǔ)句是擴(kuò)展時(shí)替換得到的。

設(shè)計(jì)宏指令時(shí)應(yīng)注意的問題宏指令可以被多次調(diào)用或被多個(gè)程序共享,在設(shè)計(jì)時(shí)需要注意以下問題:

1.宏指令說(shuō)明

2.寄存器的保存與恢復(fù)

3.宏指令中的符號(hào)說(shuō)明

6.4.2LOCAL偽指令格式:LOCAL局部符號(hào)表功能:對(duì)局部符號(hào)表中的每個(gè)符號(hào),在匯編時(shí)每擴(kuò)展一次便建立一個(gè)惟一的符號(hào),以保證匯編時(shí)生成名字的惟一性。例2.以下是定義一個(gè)延時(shí)程序的宏指令delay,并且在同一個(gè)程序中兩次被調(diào)用的擴(kuò)展情況。;宏定義DELAY MACRO LOCAL LOP MOV CX,2801LOP: LOOP LOP ENDM

…宏調(diào)用:

DELAY DELAY匯編時(shí)宏擴(kuò)展如下:

DELAY0009B90AF1 1 MOVCX,2801000CE2FE 1??0000:LOOP??0000 DELAY000EB90AF1 1 MOVCX,28010011E2FE 1??0001:LOOP??0001宏指令中參數(shù)的使用

在宏定義時(shí)可以帶有形式參數(shù),而在宏調(diào)用時(shí)給出實(shí)參數(shù)即可。宏指令的參數(shù)可以是常數(shù)、寄存器、變量、表達(dá)式、操作碼或操作碼的一部分、指令或偽指令助記符等。例3.定義在兩個(gè)字型內(nèi)存變量之間傳送數(shù)據(jù)的宏指令,并調(diào)用它,然后觀察其擴(kuò)展情況。 MOVE MACRO X,Y PUSH AX MOV AX,X MOV Y,AX POP AX ENDM

DATASEGMENT VAR1DW6543H VAR2DW ?

DATAENDS

;宏調(diào)用 ;宏擴(kuò)展

MOVEVAR1,VAR21PUSH AX 1MOVAX,VAR1 1MOVVAR2,AX 1POPAX6.4.3宏指令嵌套宏指令嵌套有兩種情況:宏定義體中含有宏調(diào)用;宏定義體中含有宏定義。DMAC MACRO MNAME,OPER ;外層宏定義

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

PUSHAX MOVAX,X OPERAX,Y MOVZ,AX POPAX ENDM ENDM例4.宏定義體中嵌套宏定義的宏指令、宏調(diào)用及宏擴(kuò)展示例。A DW 25B DW 12C DW ?

...

DMACADDITION,ADD ;外層宏調(diào)用1 ADDITIONMACROX,Y,Z1 PUSHAX1 MOVAX,X1 ADDAX,Y1 MOVZ,AX1 POPAX1 ENDM ADDITIONA,B,C ;內(nèi)層宏調(diào)用1 PUSHAX1 MOVAX,A1 ADDAX,B1 MOVC,AX1 POPAX DMACLOGIC_AND,AND ;外層宏調(diào)用1 LOGIC_ANDMACRO X,Y,Z1 PUSH AX1 MOV AX,X1 AND AX,Y1 MOV Z,AX1 POP AX1 ENDM LOGIC_ANDA,B,C ;內(nèi)層宏調(diào)用1 PUSHAX1 MOVAX,A1 ANDAX,B1 MOVC,AX1 POPAX

...使用適當(dāng)?shù)膶?shí)參數(shù),通過(guò)調(diào)用DMAC宏指令可以生成另一條新的宏指令,再調(diào)用新宏指令可以實(shí)現(xiàn)任何雙操作數(shù)指令的操作,而且兩個(gè)操作數(shù)可以同時(shí)為存儲(chǔ)器操作數(shù)。這種方法使得宏的功能更強(qiáng)大。PURGE偽指令

格式:PURGE宏指令名,……

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

PURGEINCHAR6.4.4宏操作符

這些操作符不僅適用于宏指令,也適用于重復(fù)匯編偽指令。

宏操作符格式

名稱

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

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

!字符 字符原意操作符

%表達(dá)式 表達(dá)式操作符

;;注釋 宏注釋1.操作符&

在宏定義體中&可以作為形式參數(shù)的前綴,而當(dāng)宏擴(kuò)展時(shí)則把&前后兩個(gè)符號(hào)合并形成一個(gè)符號(hào),這個(gè)符號(hào)可以是操作碼、操作數(shù)或是一個(gè)字符串。

例5.下面定義的PutData宏指令中,參數(shù)TheName作為變量名的一部分,通過(guò)&把前后兩個(gè)符號(hào)合并成一個(gè)變量名。在Jump宏指令中,參數(shù)Cond作為操作碼的一部分,通過(guò)&把前后兩個(gè)符號(hào)合并成一個(gè)指令助記符。⑴PUTDATA宏指令PUTDATA MACRO THENAME,THEDATAPD_&THENAME DB THEDATA ENDM;宏調(diào)用

PUTDATAMYDATA,5;宏擴(kuò)展

1 PD_MYDATADB5⑵JUMP宏指令

JUMP MACRO COND,L J&COND L ENDM;宏調(diào)用

JUMPNE,LAB1;宏擴(kuò)展

1 JNELAB1

在宏指令中,當(dāng)使用&操作符生成的是一個(gè)變量名或標(biāo)號(hào)時(shí),同樣要注意在一個(gè)程序中多次調(diào)用同一個(gè)宏指令時(shí)出現(xiàn)的符號(hào)重定義錯(cuò)誤。若有這種可能性,應(yīng)把名字用LOCAL偽指令說(shuō)明成局部的。如下所示:;宏定義PUTDATA0 MACROTHENAME,THEDATA LOCALPD_&THENAMEPD_&THENAMEDB THEDATA ENDM;宏調(diào)用

PUTDATA0MYDATA,5;宏擴(kuò)展

1 ??0000MYDATADB5;宏調(diào)用

PUTDATA0MYDATA,8;宏擴(kuò)展

1 ??0001MYDATADB8返回

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

例如,可以使用<>符號(hào)包圍目標(biāo),從而使該目標(biāo)作為單一的參數(shù)而不是多個(gè)參數(shù)的列表。例6.用不同的實(shí)參數(shù)調(diào)用PUTDATA宏指令,觀察它們的變化。

PUTDATA MACROTHENAME,THEDATA PD_&THENAME DBTHEDATA ENDM ;宏調(diào)用1 PUTDATAMYDATA,5,4,3 ;宏擴(kuò)展

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

;宏調(diào)用2 PUTDATAMYDATA,<5,4,3>;宏擴(kuò)展

1 PD_MYDATADB5,4,3又如以下符號(hào)定義語(yǔ)句:

Numeric=10+2 Textualequ<10+2>其匯編結(jié)果是:NUMERIC........NUMBER000CTEXTUAL........TEXT10+2

可以看到,對(duì)Numeric已經(jīng)求值,而Textual只是一串字符而已。返回3.字符原意操作符!

!操作符指示MASM把后跟的一個(gè)字符原樣傳送,即把它只作為普通字符對(duì)待。

例如,若你需要把“!&>%”符號(hào)中的一個(gè)作為宏指令中的字符,可以使用!操作符。

例7.以下宏調(diào)用的第二個(gè)實(shí)參數(shù)是一串警告信息,其中最后一個(gè)字符希望是感嘆號(hào)“!”。但“!”是宏操作符,要想把“!”當(dāng)做其原意感嘆號(hào)對(duì)待,就需在它前邊加上宏操作符!。;宏定義DEBUGMSGMACROPOINT,STRINGMSG&POINTDB’AT POINT&POINT:&STRING’ENDM;宏調(diào)用,其中第一個(gè)!為宏操作符,第二個(gè)!;是感嘆號(hào)

DEBUGMSG6,<INSERTIONFAILS!!>;宏擴(kuò)展

1 MSG6DB'ATPOINT6:INSERTIONFAILS!'4.表達(dá)式操作符%

在宏調(diào)用時(shí),%操作符強(qiáng)迫后跟的表達(dá)式立即求值,并把表達(dá)式的結(jié)果作為實(shí)參數(shù)替換,而不是表達(dá)式本身。

例8.定義Problem1宏指令,并比較兩次調(diào)用Problem1宏指令的區(qū)別,其中一次調(diào)用中使用了%操作符。

Problem1宏指令功能:把由宏指令參數(shù)所指定的字型數(shù)組(array)的一個(gè)元素裝入AX寄存器,該參數(shù)經(jīng)匯編后必須是一個(gè)常數(shù)表達(dá)式。PROBLEM1MACROPARAMETER MOVAX,ARRAY[PARAMETER*2] ENDM;宏調(diào)用1:希望取出ARRAY12,其中的參數(shù)"10+2"是表達(dá)式本身

PROBLEM110+2;宏擴(kuò)展1:

1MOVAX,ARRAY[10+2*2];實(shí)際取出的是ARRAY7,正確的表達(dá)是:;宏調(diào)用2:

PROBLEM1%10+2;宏擴(kuò)展2:

1MOVAX,ARRAY[12*2]

注意:由于MASM在調(diào)用宏指令時(shí)對(duì)其中的參數(shù)經(jīng)常是原文替換,所以有時(shí)產(chǎn)生的可能不是預(yù)期的結(jié)果??紤]以下對(duì)PROBLEM1的宏調(diào)用及宏擴(kuò)展:;宏調(diào)用,要求裝入ARRAY的元素2

PROBLEM12;宏擴(kuò)展

1 MOVAX,ARRAY[2*2]

可以看到,宏擴(kuò)展后結(jié)果正確。;宏調(diào)用:裝入ARRAY的元素10:

INDEX=8 PROBLEM1INDEX+2;宏擴(kuò)展

1 MOVAX,ARRAY[INDEX+2*2]

因?yàn)镸ASM的地址表達(dá)式遵守操作符優(yōu)先級(jí)的優(yōu)先規(guī)則,則該語(yǔ)句宏擴(kuò)展后不是預(yù)想的結(jié)果,它訪問的是元素6(索引12),而不是元素10(索引20)。

為了能夠得到正確的結(jié)果,可以在宏指令的參數(shù)表達(dá)式中用()把參數(shù)括起來(lái):;宏定義PROBLEM2MACROPARAMETER MOVAX,ARRAY[(PARAMETER)*2] ENDM;宏調(diào)用

INDEX=8 PROBLEM2INDEX+2;宏擴(kuò)展

1 MOVAX,ARRAY[(INDEX+2)*2]5.宏注釋;;

在宏定義中,若注釋以一個(gè)分號(hào)開始,則該注釋在宏擴(kuò)展時(shí)出現(xiàn)。但若注釋以兩個(gè)分號(hào)開始,則該注釋在宏擴(kuò)展時(shí)不出現(xiàn)。舉例見列表偽指令。返回6.4.5列表偽指令

格式

功能

.LALL

在列表文件中列出全部宏文本內(nèi)容 (以雙分號(hào)開頭的注釋除外)

.SALL

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

.XALL

(缺?。┰诹斜砦募兄涣谐隹僧a(chǎn)生 目標(biāo)代碼的宏文本內(nèi)容注意:這些列表偽指令只影響列表文件,并不影響目標(biāo)碼的生成。6.5宏指令庫(kù)

為了使宏指令能讓多個(gè)程序共享,可以把它們組織到一個(gè)文件中,并存放在磁盤上,把這種文件稱為宏指令庫(kù)。1.建立宏指令庫(kù)

可以把一些常用的宏指令集中在一個(gè)文件中形成宏指令庫(kù),用EDIT等任何文本編輯程序創(chuàng)建宏指令庫(kù),庫(kù)名由用戶自己起,而且對(duì)庫(kù)的擴(kuò)展名沒有特殊要求。庫(kù)中的宏指令以源代碼形式出現(xiàn)。

假設(shè)MACRO.LIB中包含以下宏指令(詳細(xì)內(nèi)容見教材P174):SETMODE ;設(shè)置80*25彩色顯示模式INCHAR ;接收一個(gè)字符,并返回在AL中OUTCHARX ;輸出X字符PUSHREG;保存寄存器DX、CX、BX、AX、DI、SI、BPPOPREG;恢復(fù)寄存器BP、SI、DI、AX、BX、CX、DXWINDOW MACRO

Collor,WleftTopRow,WLeftTopCul, WRightBottomRow,WRightBottomCul ;功能:開窗口MOVEMOCROX,Y ;字型數(shù)據(jù)X送Y變量CLRSCRN ;清屏CURSOR ;置光標(biāo),入口參數(shù):DH:DL=行,列號(hào)RETURN ;返回操作系統(tǒng)BIN_DEC MACRO ASC,BIN;功能:把16位二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)的;ASCII值,ASC為5個(gè)字節(jié)的十進(jìn)制數(shù)緩沖區(qū),;BIN為要轉(zhuǎn)換的二進(jìn)制數(shù)。

DISPMACROASC;顯示首址為ASC的字符串2.把宏指令庫(kù)包含到應(yīng)用程序中格式:INCLUDE源文件名功能:把另一個(gè)源文件包含到當(dāng)前源文件中。3.使用宏指令庫(kù)中的宏指令

例9.實(shí)現(xiàn)32位二進(jìn)制數(shù)除以16位二進(jìn)制數(shù),并把結(jié)果用十進(jìn)制數(shù)形式顯示在屏幕上。編碼見程序6.9。程序6.9 INCLUDE MACRO.LIB PURGE SETMODE,INCHAR,OUTCHAR, WINDOW,MOVE,MULSTACKSG SEGMENT STACK'S' DW 16 DUP('?')STACKSG ENDSDATA SEGMENTA DD 7006652 ;被除數(shù)B DW 1234 ;除數(shù)C DW ? ;商PROMPT DB 'Theresultis:$'ASCII DB 5 DUP(?),'$' ;轉(zhuǎn)換結(jié)果DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKSGMAIN PROC FAR MOV AX,DATA MOV DS,AX MOV DX,WORDPTRA+2 MOV AX,WORDPTRA DIV B BIN_DEC ASCII,AX CLRSCRN DISP PROMPT DISP ASCII RETURNMAIN ENDPCODE ENDS END MAIN4.宏指令與子程序的區(qū)別采用宏和子程序均能達(dá)到代碼共享、簡(jiǎn)化源程序的目的;它們的區(qū)別主要有以下幾點(diǎn):(1)

工作方式的區(qū)別(2)參數(shù)傳遞的方便性(3)參數(shù)的多樣性及靈活性

通常:宏指令被用在代碼較短且參數(shù)較多的場(chǎng)合;子程序被用在代碼較長(zhǎng)的場(chǎng)合。6.6重復(fù)偽指令

當(dāng)程序中需要重復(fù)書寫相同或幾乎相同的語(yǔ)句時(shí),可以用重復(fù)偽指令定義重復(fù)塊,以簡(jiǎn)化程序和減輕程序設(shè)計(jì)人員的工作量。絕大部分MASM版本提供了REPT、IRP和IRPC重復(fù)偽指令,而在MASM6.X中還提供了其它重復(fù)偽指令。6.6.1重復(fù)偽指令REPT

格式:

REPT 數(shù)值表達(dá)式 ... ;重復(fù)塊

ENDM

功能:匯編程序使重復(fù)塊的內(nèi)容重復(fù)多次,重復(fù)次數(shù)由表達(dá)式給出。

說(shuō)明:重復(fù)塊中可以出現(xiàn)任何有效的匯編語(yǔ)句,數(shù)值表達(dá)式的計(jì)算結(jié)果應(yīng)該是無(wú)符號(hào)常數(shù)。DATA SEGMENTTABLE LABEL WORD X=5 REPT6 ;重復(fù)6次

DWX*X*X ;定義立方值

X=X+1 ENDMDATA ENDS匯編后的情況如下:(1)0000 DATA SEGMENT(2)0000 TABLE LABELWORD(3)=0005 X=5(4) REPT6(5) DWX*X*X(6) X=X+1(7) ENDM (8)0000 007D 1 DW X*X*X (9)0002 00D8 1 DW X*X*X (10)0004 0157 1 DW X*X*X (11)0006 0200 1 DW X*X*X (12)0008 02D9 1 DW X*X*X (13)000A 03E8 1 DW X*X*X (14)000C DATAENDS

第(8)到第(13)行是匯編后的情況。在代碼段中可以通過(guò)TABLE名來(lái)引用這些值。MOVBX,10REPT2 DECBXENDM匯編后產(chǎn)生如下語(yǔ)句:

MOVBX,101 DECBX1 DECBXCHARS MACRO NUM MOV AH,2 CHAR='A' REPT NUM MOVDL,CHAR INT21H CHAR=CHAR+1 ENDM ENDM CODE SEGMENT ASSUME CS:CODE MAIN PROC FAR CHARS 26 MOV AX,4C00H INT 21H MAIN ENDP CODE ENDS END MAIN

從本例可以看出,重復(fù)偽指令可以出現(xiàn)在宏指令中。CHARS MACRO NUM MOV AH,2 CHAR='A' REPT NUM MOVDL,CHAR INT21H CHAR=CHAR+1 ENDM ENDM0000 CODE SEGMENT ASSUMECS:CODE0000 MAIN PROCFAR CHARS260000B402 1 MOVAH,20002B241 2 MOVDL,CHAR;字符A0004CD21 2 INT21H0006B242 2 MOVDL,CHAR;字符B0008CD21 2 INT21H

…0066B25A 2 MOVDL,CHAR;字符Z0068CD21 2 INT21H006AB84C00 MOVAX,4C00H006DCD21 INT21H006F MAIN ENDP006F CODE ENDS END MAIN6.6.2不定重復(fù)偽指令1.IRP偽指令

格式:

IRP 形式參數(shù),<實(shí)參數(shù)> ... ;重復(fù)塊

ENDM

功能:匯編程序使重復(fù)塊的內(nèi)容重復(fù)多次,重復(fù)次數(shù)由實(shí)參數(shù)個(gè)數(shù)決定。每次重復(fù)都用尖括號(hào)中的一個(gè)實(shí)參數(shù)替代形式參數(shù),依次使用實(shí)參數(shù),直到用完為止。

例1.實(shí)參數(shù)可以是符號(hào)。

IRPREG,<AX,BX,CX,DX> PUSHREG ENDM

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

1 PUSH AX 1 PUSH BX 1 PUSHCX 1 PUSHDX IRP X,<1,2,3+5,'EDIT'> DBX ENDM匯編后產(chǎn)生的.LST文件:000001 1DB1 ;數(shù)字000102 1DB2 ;數(shù)字000208 1DB3+5 ;常數(shù)表達(dá)式0003454449541DB‘EDIT’

;ASCII值

從目標(biāo)碼部分可以看出,數(shù)字1、2生成01、02,3+5計(jì)算后其值為8,'EDIT'生成相應(yīng)的ASCII值45、44、49、54。2.IRPC偽指令

格式:

IRPC 形式參數(shù),數(shù)字串 ... ;重復(fù)塊

ENDM

功能:匯編程序使重復(fù)塊的內(nèi)容重復(fù)多次,重復(fù)次數(shù)由數(shù)字串中數(shù)字位數(shù)決定。每次重復(fù)都用數(shù)字串中一個(gè)數(shù)字替代形參,依次使用串中的數(shù)字,直到用完為止。

說(shuō)明:重復(fù)塊中可以出現(xiàn)任何有效的匯編語(yǔ)句。

例2.定義一串?dāng)?shù)字。

IRPC Z,1235 DBZ ENDM

匯編后生成的

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論