版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年高性能傳輸線纜項(xiàng)目資金需求報(bào)告代可行性研究報(bào)告
- 系統(tǒng)功能分析
- 背離技術(shù)分析-江南小隱
- 紡織品英語(yǔ)詞匯
- 第一章 地球單元綜合檢測(cè) 2024-2025學(xué)年七年級(jí)地理上冊(cè)同步備課系列(人教版2024)
- 《1 例乳蛾咽痛患兒的護(hù)理體會(huì)》
- 保鮮用品購(gòu)銷合同范本(標(biāo)準(zhǔn)版)
- 廣告制作合同正規(guī)版范文(標(biāo)準(zhǔn)版)
- 江西省南昌市東湖區(qū)南昌十中2022年高考考前模擬物理試題含解析
- 橋梁臺(tái)架出售協(xié)議書模板
- 2024廣東東莞市煙草專賣局(公司)招聘9人(高頻重點(diǎn)提升專題訓(xùn)練)共500題附帶答案詳解
- 2024版Purchase Contract(采購(gòu)合同范本英文版)
- 4.1 10的再認(rèn)識(shí)-一年級(jí)上冊(cè)數(shù)學(xué)課件
- 新質(zhì)生產(chǎn)力與高質(zhì)量發(fā)展答案-2024公需課
- 2024年山西晉城高平市綜治中心招聘專職網(wǎng)格員136人歷年(高頻重點(diǎn)復(fù)習(xí)提升訓(xùn)練)共500題附帶答案詳解
- 10J301 地下建筑防水構(gòu)造
- 中國(guó)移動(dòng)投資生態(tài)白皮書(2024年版)
- 蘇科版(2015)信息技術(shù)五年級(jí) 第3課 火柴人跳舞 課件
- 《習(xí)作:這兒真美》( 教學(xué)設(shè)計(jì))2023-2024學(xué)年統(tǒng)編版語(yǔ)文三年級(jí)上冊(cè)
- 中國(guó)急性缺血性卒中診治指南(2023)解讀
- 高等教育學(xué)復(fù)習(xí)題庫(kù)
評(píng)論
0/150
提交評(píng)論