匯編語言程序設計(劉慧婷第3版)微課版 課件 第8、9章 子程序設計、宏匯編及其它高級偽操作_第1頁
匯編語言程序設計(劉慧婷第3版)微課版 課件 第8、9章 子程序設計、宏匯編及其它高級偽操作_第2頁
匯編語言程序設計(劉慧婷第3版)微課版 課件 第8、9章 子程序設計、宏匯編及其它高級偽操作_第3頁
匯編語言程序設計(劉慧婷第3版)微課版 課件 第8、9章 子程序設計、宏匯編及其它高級偽操作_第4頁
匯編語言程序設計(劉慧婷第3版)微課版 課件 第8、9章 子程序設計、宏匯編及其它高級偽操作_第5頁
已閱讀5頁,還剩153頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第8章子程序設計

為了使程序結構更加清晰,把程序需要完成的任務分解為若干個子任務,把每個子任務設計成一個相對獨立的程序,稱為子程序,也稱為過程。8.1子程序結構8.1.1子程序調(diào)用指令8.1.2過程定義與過程結構

8.1.3保護和恢復現(xiàn)場寄存器8.1.1子程序調(diào)用指令子程序定義:在模塊化程序設計中,經(jīng)常把程序中某些具有獨立功能的部分編寫成獨立的程序模塊,稱為子程序。主程序通過CALL指令調(diào)用子程序。子程序執(zhí)行完畢后通過RET指令回到主程序。(1)CALL調(diào)用指令格式:CALLDST操作:首先把下一條指令的地址(返回地址)壓入堆棧保存,再把子程序的入口地址置入IP(CS)寄存器,以便實現(xiàn)轉(zhuǎn)移。對于段內(nèi)調(diào)用,只是向堆棧保存IP寄存器的值。對于段間調(diào)用,是先向堆棧保存CS寄存器的值,再向堆棧保存IP寄存器的值。(2)RET返回指令格式1:RET格式2:RETEXP操作:把堆棧里保存的返回地址送回IP(CS)寄存器,實現(xiàn)程序的返回。對于段內(nèi)調(diào)用,彈出一個字到IP寄存器。對于段間調(diào)用,先彈出一個字到IP寄存器,再彈出一個字到CS寄存器。例8.1例8.1代碼段1中的主程序A調(diào)用代碼段2中的子程序B,程序B調(diào)用代碼段2中的子程序C,調(diào)用關系如圖8-1所示,堆棧情況如圖8-2所示。 主程序A程序B程序C ………………CALLFARPTRBCALLNEARPTRCRET(IP=2000H,CS=3400H)(IP=1000H,CS=6200H)………… RET8.1.2過程定義與過程結構過程定義偽指令

Procedure_NamePROCAttribute┇Procedure_NameENDP如:

mainprocfar/near┇mainendp過程名是標識符,起到標號的作用,是子程序入口的符號地址。過程的屬性可以是FAR或NEAR類型。對過程屬性的確定原則是:NEAR為近,是段內(nèi)調(diào)用。FAR類型為遠,是跨段調(diào)用。如調(diào)用程序和子程序在同一代碼段,則使用NEAR屬性;如調(diào)用程序和子程序不在同一代碼段,則使用FAR屬性。主程序的過程定義屬性應為FAR。

例8.2調(diào)用程序和子程序在同一個代碼段,調(diào)用程序和子程序并列。 mainprocfar … callsubr… ret mainendp subrprocnear… ret subrendp調(diào)用程序和子程序在同一個代碼段,調(diào)用程序和子程序相互嵌套。 mainprocfar … callsubr … ret subrprocnear … ret subrendp mainendp例8.3調(diào)用程序和子程序不在同一個代碼段。 code1segment … mainprocfar … callsubr … ret mainendp code1ends … code2segment … callsubr … subrprocfar … ret subrendp code2ends8.1.3保存和恢復現(xiàn)場寄存器子程序調(diào)用CALL:首先將返回地址壓棧,然后把子程序的入口地址送入IP/CS寄存器。子程序返回RET:將堆棧里保存的返回地址送回IP/CS寄存器。在子程序中對主程序的現(xiàn)場實施保護和恢復在進入子程序后,對將要使用的寄存器,先保存這些寄存器的值,在子程序退出前恢復這些寄存器的值。保存和恢復寄存器

8.2子程序的參數(shù)傳遞入口參數(shù)(調(diào)用參數(shù)):主程序傳遞給子程序。出口參數(shù)(返回參數(shù)):子程序返回給主程序。傳遞的參數(shù):值傳遞和地址傳遞。8.2.1用寄存器傳遞參數(shù)

用寄存器傳遞參數(shù)就是約定某些寄存器存放將要傳遞的參數(shù)。該方法簡單,執(zhí)行的速度也很快。但由于寄存器數(shù)量有限,不能用于傳遞很多的參數(shù)。例8.4從鍵盤輸入一個十進制數(shù)(小于65536的正數(shù)),顯示輸出該數(shù)的十六進制形式。通過寄存器傳送變量。算法分析1.輸入的十進制數(shù)整合成二進制數(shù);

2.整合的方法A(n)=A(n-1)*10+B(n);

3.二進制數(shù)轉(zhuǎn)化為十六進制顯示。程序結構框圖DTOB子程序流程圖 dtohexsegment assumecs:dtohex mainprocfar pushds xorax,ax pushax calldtob;十進制數(shù)鍵盤輸入整合為二進制 callcrlf;輸出回車換行 callbtoh;二進制轉(zhuǎn)為十六進制顯示

ret mainendp dtobprocnear movbx,0 input:movah,1;鍵盤輸入

int21h subal,30h;把ascii碼轉(zhuǎn)變?yōu)閿?shù)值 jlexit;如不是數(shù)則退出 cmpal,9 jgexit;如不是數(shù)則退出 cbw;擴展為字 xchgax,bx;交換寄存器 movcx,10 mulcx;a(n)=a(n-1)×10 addax,bx;a(n)=a(n)+b(n)xchgax,bx;交換寄存器 jmpinput exit:ret dtobendp btohprocnear movch,4;準備輸出4位十六進制數(shù) shift:movcl,4;每次需移4位 rolbx,cl moval,bl andal,0fh;取最右4位 addal,30h;轉(zhuǎn)為ascii cmpal,39h jledig;是0~9則轉(zhuǎn)dig addal,7;是A~F dig:movdl,al;顯示 movah,2 int21h decch jnzshift ret btohendp crlfprocnear movdl,0dh movah,2 int21h movdl,0ah movah,2 int21h ret crlfendp dtohexends endmain討論1.畫出程序調(diào)用過程中堆棧的變化情況;2.畫出DTOB,BTOH的程序流程圖,并闡述算法思想;8.2.2用變量傳遞參數(shù)參數(shù)較多時可以用約定的變量在過程間傳遞參數(shù)。例8.5鍵盤輸入字符串到緩沖區(qū)后,對緩沖區(qū)內(nèi)容降序排序并輸出。datasegment buffdb16;緩沖區(qū)大小 numbdb?;輸入的字節(jié)數(shù) arrydb16dup(?);緩沖區(qū)內(nèi)容dataendscodesegment assumecs:code,ds:datamainprocfar pushds subax,ax pushax movax,data movds,ax callorder retmain endporderprocnear leadx,buff;輸入緩沖區(qū) movah,10 int21h movcl,numb;實際輸入個數(shù)deccl movch,0lp1: movdi,cx movbx,0;下標lp2: moval,arry[bx]

cmpal,arry[bx+1] jgecont xchgal,arry[bx+1] movarry[bx],alcont:incbx decdi jnzlp2

looplp1 calloutput retorder endp;------------------outputprocnearmovbl,numb;后面插入$以便顯示

movbh,0movbyteptr[arry+bx],'$'movdx,offsetarrymovah,9int21hretoutput endpcode endsendmain討論1.畫出降序排序的流程圖,并簡述算法思想;2.這兩個例題是利用了寄存器和變量的什么性質(zhì),實現(xiàn)參數(shù)傳遞的?8.2.3用地址表傳遞參數(shù)的通用子程序在主程序中建立一個地址表,把要傳遞的參數(shù)地址放在地址表中,然后把地址表的首地址放入寄存器,子程序通過寄存器間接尋址方式從地址表中取得所需參數(shù),可以設計通用子程序處理其他類似字符串排序問題。例8.6采用通過地址表傳遞參數(shù)地址的方法,鍵盤輸入緩沖區(qū)并對其內(nèi)容排序和輸出。datasegment buffdb16 numbdb? arrydb16dup(?) tabledw3dup(?);地址表dataendscodesegment assumecs:code,ds:datamain procfar pushds subax,ax pushax movax,data movds,ax movtable,offsetbuff movtable+2,offsetnumb movtable+4,offsetarry movsi,offsettable;地址表首地址送si callorder retmainendporder procnear movdx,[si] movah,10 int21h movdi,[si+2] movcl,[di];實際輸入個數(shù)送cxdeccl movch,0

lp1: movdi,cx movbx,[si+4];bx指向緩沖區(qū)lp2: moval,[bx] cmpal,[bx+1] jgecont xchgal,[bx+1] mov[bx],alcont:incbx decdi jnzlp2

looplp1 calloutput retorder endp;------------------outputprocnearmovdi,[si+2];后面插入$以便顯示movbl,[di]movbh,0movdi,[si+4]movbyteptr[di+bx],'$'movdx,di movah,9int21hretoutput endpcode endsendmain思考題畫出數(shù)據(jù)段中數(shù)據(jù)的存放情況,并用指針標注出數(shù)據(jù)之間的關系。為了實現(xiàn)在cx中存放字符串的實際長度,進行了幾次尋址,每一次是什么尋址方式;為了實現(xiàn)每一輪中兩個數(shù)的比較,對參與比較的兩個數(shù)進行了幾次尋址,每一次是什么尋址方式。8.2.4用堆棧傳遞參數(shù)的通用子程序用堆棧傳遞參數(shù)地址

,可以設計通用子程序。例8.7鍵盤輸入緩沖區(qū)內(nèi)容排序并輸出,用堆棧傳遞參數(shù)地址。datasegment dw50dup(?);堆棧50個字 toslabelword;棧頂?shù)刂穞os buffdb16 numbdb? arrydb16dup(?)dataendscodesegmentassumecs:code,ds:data,ss:datamainprocfar ;設置ss和sp movax,data movss,ax leasp,tos ;ds和0壓入堆棧,以便返回dos pushds xorax,ax pushax movax,data movds,ax ;參數(shù)地址壓入堆棧 leabx,buff pushbx;buff的地址壓入堆棧 leabx,numb pushbx;numb的地址壓入堆棧 leabx,arry pushbx;arry的地址壓入堆棧 callorder retmainendporderprocnear movbp,sp movdx,[bp+6];buff地址送dx movah,10 int21h movdi,[bp+4];取numb的地址 movcl,[di]deccl movch,0;numb送cx

lp1: movdi,cx movbx,[bp+2];arry的地址送bxlp2:moval,[bx]

cmpal,[bx+1] jgecont xchgal,[bx+1] mov[bx],alcont:incbx decdi jnzlp2looplp2 calloutput ret6;修改sp指針并返回order endp;------------------outputprocnearmovdi,[bp+4];后面插入$以便顯示movbl,[di]movbh,0 movdi,[bp+2]movbyteptr[di+bx],'$'movdx,di movah,9int21hretoutput endpcode endsendmain思考題程序初始時tos的值是多少?畫出程序執(zhí)行過程中,堆棧段中的存儲情況8.2.5用結構變量傳遞參數(shù)的通用子程序結構就是把邏輯上互相關聯(lián)的一組數(shù)據(jù)以某種形式組合在一起。在程序中,若要多次使用相同的一組數(shù)據(jù)格式,那么我們就可以把這一組數(shù)據(jù)格式定義為一個結構數(shù)據(jù)。結構類型的定義:結構名STRUC……結構名ENDSSTRUC偽指令只是定義了一種結構模式,還沒有生成結構變量。用結構預置語句生成結構變量并賦值。結構預置語句格式:變量結構名<各字段賦值>對結構字段初值的修改,并非所有字段的初值都可以修改,只有簡單結構字段和字符串字段初值才可以修改。簡單結構字段是指由偽指令DB、DW或DD定義的單項變量。多項變量的結構字段初值不能修改。例如下面就是多項的結構字段:

DW10DUP(?)DB12H,34HDB‘ABCD’,’1234’例8.8定義一個名為STUDENT的結構類型。STUDENTSTRUCIDDB‘AAAAAAAA’NAMEDB3DUP(0)JF1DW22HJF2DW?JF3DW?JF4DW?STUDENTENDS例8.9結構變量預置語句(定義結構變量)STD1STUDENT<’A2031456’,,,33H>STD2STUDENT<>STDSSSTUDENT100DUP(<>)例8.10結構變量的訪問

MOVSI,1LEABX,STD1MOVAL,STD1.NAME[SI];變量STD1的字段NAME的第2項送ALMOVAL,[BX].NAME[SI];變量STD1的字段NAME的第2項送ALMOVDL,STDSS+3*19.NAME[SI];變量STDSS第4條記錄的字段NAME的第2項送AL例8.11鍵盤輸入緩沖區(qū)內(nèi)容排序并輸出,用堆棧傳遞參數(shù)地址,使用結構類型.

datasegment dw50dup(?);堆棧50個字

toslabelword;棧頂?shù)刂穞os buffdb16 numbdb? arrydw16dup(?)data endscode segment assumecs:code,ds:data,ss:datamain procfar ;設置ss和sp movax,data movss,ax leasp,tos ;ds和0壓入堆棧,以便返回dos pushds xorax,ax pushax movax,data movds,ax ;參數(shù)地址壓入堆棧 leabx,buff pushbx;buff的地址壓入堆棧 leabx,numb pushbx;numb的地址壓入堆棧

leabx,arry pushbx;arry的地址壓入堆棧

callorder retmain endporderprocnear parstruc pipdw? p3dw? p2dw? p1dw? parends movbp,sp movdx,[bp].p1 ;buff的地址送dx movah,10 int21h movdi,[bp].p2;取numb的地址

movcl,[di] ;numb送cx decclmovch,0

lp1:movdi,cx movbx,[bp].p3;arry地址送bx lp2:moval,[bx] cmpal,[bx+1] jgecont xchgal,[bx+1] mov[bx],alcont:incbx decdi jnzlp2 looplp1calloutput ret6;修改sp指針并返回order endpcodeends endmain;------------------outputprocnearmovdi,[bp].p2movbl,[di]movbh,0movdi,[bp].p3movbyteptr[di+bx],'$'movdx,di movah,9int21hretoutput endpcode endsendmain思考題畫出執(zhí)行指令callorder后,堆棧段中的數(shù)據(jù)存儲情況。8.3多模塊程序設計

多模塊程序設計中,各個模塊獨立編寫,分別匯編,便于程序的編寫,調(diào)試和維護。8.3.1多模塊之間的參數(shù)傳遞局部符號和外部符號在本模塊中定義,又只在本模塊中引用的符號叫局部符號。

在本模塊中定義,而在另一模塊中引用的符號叫外部符號。對于外部符號,編程時需要明確說明。EXTRN符號名:類型[,…]

在另一個模塊中定義而要在本模塊中使用的符號必須使用EXTRN偽操作說明。符號名為變量時,則type應為BETY,WORD,DWORD等;如符號名為標號或過程名,則type應為NEAR或FAR。PUBLIC符號名1,符號名2,……

在一個模塊中定義的符號(包括變量、標號、過程名等)在提供給其他模塊使用時,必須要用PUBLIC定義。例8.12主程序鍵盤輸入緩沖區(qū),子程序?qū)彌_區(qū)內(nèi)容排序并輸出,采用獨立模塊。;812main.asmpublicbuff,numb,arryextrnorder:fardatasegment buffdb16 numbdb? arrydb16dup(?)dataendscodesegmentassumecs:code,ds:datamainprocfar pushds subax,ax pushax movax,data movds,ax leadx,buff movah,10 int21h callorder retmain endpcodeends endmain;812sub.asmpublicorderextrnbuff:byte,numb:byte,arry:bytecodesegmentassumecs:codeorderprocfar movcl,numb movch,0 movdi,cx lp1:movcx,di movbx,0 lp2:moval,arry[bx] cmpal,arry[bx+1] jgecont xchgal,arry[bx+1] movarry[bx],al cont:incbx looplp2 decdi jnzlp1 movbl,numb movbh,0 movbyteptr[arry+bx],'$' movdx,offsetarry movah,9 int21h retorder endpcode ends end各模塊先分別匯編,然后再連接:Link812main+812subLink的次序影響結果,主模塊在前面。codesegment assumeds:data,cs:codemainprocfar(1)(2)(3)………retmainendpcodeendsendmain此處添加題目描述MOVAX,DATAPUSHDSXORAX,AXPUSHAXABCD提交MOVDS,AXE多選題50分datasegmentdw100dup(?)toslabelworddataendscodesegment assume cs:code,ss:datamainprocfar()()()pushdsxorax,axpushaxcallfarptrsuba…;假定此處指令的地址為CS=3400h,IP=30h……codeendsendmain此處添加題目描述MOVAX,DATAMOVSS,AXMOVDS,AXMOVSP,TOSABCD提交LEASP,TOSE多選題50分編程題在數(shù)據(jù)段定義一個緩沖區(qū)在主程序中完成從鍵盤輸入一個字符串到緩沖區(qū),再從鍵盤輸入單個字符;在查找子程序中查找緩沖區(qū)中該字符出現(xiàn)的次數(shù);在顯示子程序中把該字符出現(xiàn)的次數(shù)存入內(nèi)存中并顯示出來。8.3.2顯示十進制數(shù)的通用模塊例8.13從鍵盤輸入一個十六進制數(shù)(不超過四位),顯示輸出該數(shù)的十進制形式。

算法分析:

1.輸入的十六進制數(shù)轉(zhuǎn)化為二進制數(shù);

2.把二進制數(shù)用十進制顯示;

3.輾轉(zhuǎn)相除法。主程序文件HTODPRO.ASMextrnhtob:far,crlf:far,btod:farcodesegment assumecs:codemainprocfar pushds xorax,ax pushax callhtob callcrlf callbtod retmainendpcodeends endmain子程序文件htobpro.asmpublichtobcode1segment assumecs:code1htobprocfarstart:movbx,0;初始化 movch,4 movcl,4inchr:movah,1;鍵盤輸入 int21h cmpal,30h jlexit ;非法輸入 cmpal,39h jledig;輸入是數(shù)字0~9 cmpal,41h jlexit;非法輸入 cmpal,46h jgexit;非法輸入 subal,37h;輸入是大寫A~F jmpls4dig: subal,30h ls4: shlbx,cl addbl,al decch jnzinchrexit: rethtobendpcode1endsend子程序文件btodpro.asmpublicbtodcode2segment assumecs:code2btodprocfar movcx,10000 callddiv movcx,1000 callddiv movcx,100 callddiv movcx,10 callddiv movcx,1 callddiv retbtod endpddivprocnear movax,bx movdx,0 divcx movbx,dx movdl,al adddl,30h movah,2 int21h retddiv endpcode2ends end子程序文件crlfpro.asmpubliccrlfcode3segment assumecs:code3crlfprocfar movdl,0ah movah,2 int21h movdl,0dh movah,2 int21h retcrlf endpcode3endsend8.3.3C語言程序調(diào)用匯編語言子程序匯編語言程序占用內(nèi)存空間小,運行速度快,能夠直接控制硬件。高級語言編寫人機交互界面和數(shù)據(jù)分析處理程序比較方便。用高級語言編寫主程序,匯編語言編寫子程序。分別編譯/匯編成目標文件。連接形成可執(zhí)行文件。參數(shù)、調(diào)用和命名的規(guī)定(1)C語言通過堆棧向匯編語言傳送參數(shù)。(2)C語言程序?qū)ν獠窟^程須以EXTERN說明,在匯編語言子程序中必須在過程名前加下劃線,并說明為PUBLIC。(3)C語言和匯編語言程序必須使用相同的存儲模型。(4)匯編語言程序的返回參數(shù)放在AX寄存器(整型)。例8.14C語言程序調(diào)用匯編語言程序,求兩個數(shù)中的較大數(shù)。/*主程序my_c.c*/externintmax(int,int);main(){intb; b=max(4,6);/*b=AX*/ printf("maxis%d",b);};------------------;子程序my_h.asm.modelsmallpublic_max.code_maxprocnear pushbp movbp,sp movax,[bp+4] cmpax,[bp+6] jgexit movax,[bp+6];AX寄存器中的最大值返回給C程序exit: popbp ret_maxendp end操作過程:1.對MY_H.ASM匯編:MASMMY_H/MX(加/MX是為了生成小寫函數(shù)名,以適應C程序)2.在TC集成環(huán)境中,在菜單條上選擇Option/Compiler/Model,在Model的選擇窗口選項中選擇所需要的存儲模型,這里選small。編譯MY_C.C程序。3.建立PRJ工程文件,文件內(nèi)容為:MY_C.CMY_H.ASM在菜單條上選擇Compile,并設立主文件為MY_C.C,然后選LINKEXEFILE。于是連接成EXE文件。在TC++集成環(huán)境中,設成.C文件也可以。第9章宏匯編及其它高級偽操作

宏匯編語言提供了類似于高級語言的某些復雜功能,如宏匯編、重復匯編與條件匯編,提高了使用匯編語言進行程序設計的質(zhì)量和效率。9.1宏匯編宏是源程序中一段有獨立功能的程序代碼。它只需要在源程序中定義一次,就可以多次調(diào)用,調(diào)用時只需要用一個宏指令語句就可以了。宏功能既可以實現(xiàn)程序復用,又能方便的傳遞多個參數(shù)。子程序優(yōu)點:省存儲空間優(yōu)化程序結構便于調(diào)試和修改子程序缺點:調(diào)用、返回、保存、恢復需花開銷參數(shù)傳遞復雜因此,在程序較短,或需要傳送的參數(shù)較多的情況下,用宏匯編更加有利。9.1.1宏定義、宏調(diào)用和宏展開宏定義:宏指令名MACRO[形參1,形參2,…]<宏定義體>ENDM宏定義體是一組有獨立功能的程序代碼。宏指令名給出宏定義的名稱,調(diào)用時就使用宏指令名來調(diào)用宏定義。第一個符號必須是字符。啞元表給出了宏定義中所用到的形式參數(shù),每個啞元之間用逗號隔開。宏調(diào)用:宏指令名[實參1,實參2,…]宏指令被定義后,在源程序中就可以直接調(diào)用,稱為宏調(diào)用。一般說來,實參的個數(shù)應和形參的個數(shù)相等,但匯編程序并不要求它們必須相等。若實參個數(shù)大于形參個數(shù),則多余的實參不予考慮,若實參個數(shù)小于形參個數(shù),則多余的形參取空值。宏展開:在對源程序的匯編階段,匯編程序?qū)υ闯绦蛑械拿總€宏調(diào)用都進行了宏展開,即用宏定義體取代源程序中宏指令名,用實參取代形參。應該注意,用實參取代形參后,所得到的語句應該是有效的,否則匯編程序?qū)甘境鲥e。例9.1用宏指令實現(xiàn)兩數(shù)的相加。宏定義:sumnMACROx,y,result movax,x

addax,y

movresult,ax ENDMsumnMACROx,y,result

movax,x

addax,y

movresult,ax

ENDM宏展開:1movax,341addax,251movbx,ax

宏調(diào)用:sumn34,25,bx

例9.2用宏指令實現(xiàn)兩個八位有符號數(shù)的乘法。宏定義:imultiplyMACROx,y,result pushax moval,x

imuly

movresult,ax popax ENDM宏展開:1pushax1moval,cl1imuldl1mov[bx],ax1popax┇1pushax1moval,ary1imulvar1movsave,ax1popax宏調(diào)用:imultiplycl,dl,[bx]…imultiplyary,var,save例9.3某工廠工人的周工資由計時工資和計件工資組成,計時工資按每小時工資率RATE乘以工作小時數(shù)計算;計件工資按超定額部分乘以SUP計算(超定額=實際完成的工件數(shù)MADE-定額工件數(shù)PART),工資總額放在WAGE中。宏定義如下:

wagesmacrorate,hour,made,part,supwage=rate*hour+(made-part)*supendmrate=5part=100sup=4宏調(diào)用:wagesrate,40,120,part,sup宏展開為:wage=rate*40+(120-part)*sup從以上兩個例子可以看出,子程序和宏指令具有類似的功能,但又有以下區(qū)別:空間的區(qū)別:宏指令并不節(jié)省目標程序的空間,而子程序在目標程序中只有一段;時間的區(qū)別:宏指令在運行時不需要其他額外的CPU開銷,而子程序的調(diào)用、返回和保護現(xiàn)場、恢復現(xiàn)場需要占用時間;參數(shù)的區(qū)別:宏調(diào)用可實現(xiàn)多個參數(shù)的直接代換,方式簡單靈活,而子程序參數(shù)傳遞麻煩。

9.1.2宏定義的嵌套這種嵌套結構的特點是外層宏定義的宏體中又有宏定義,只有調(diào)用外層宏定義一次后,才能調(diào)用內(nèi)層宏指令。例9.4用嵌套的宏定義實現(xiàn)兩個八位數(shù)的算術運算。宏定義:mathMACROmathname,action,nummathnameMACROx,y,result pushax movnum,x actiony movresultax popax ENDMENDM宏調(diào)用:

mathimultiply,imul,al宏展開:imultiplyMACROx,y,resultpushaxmoval,ximulymovresult,axpopax ENDM宏調(diào)用:

mathdivide,div,ax宏展開:divideMACROx,y,resultpushax movax,xdivy movresult,ax popax ENDM接下來可使用宏調(diào)用:divideary,var,save則宏展開如下:1pushax1movax,ary1divvar1movsave,ax1popax9.1.3宏定義中使用宏調(diào)用宏定義中使用的宏調(diào)用必須已經(jīng)定義。例9.5用宏指令實現(xiàn)顯示字符。宏定義:INT21MACROFUNCTN MOVAH,F(xiàn)UNCTN INT21H ENDMDISPCMACROCHAR MOVDL,CHAR INT212 ENDM宏調(diào)用:DISPC‘A’宏展開: 1MOVDL,‘A’ 2MOVAH,2 2INT21H這里的2表示第二層展開結果。9.1.4帶間隔符的實參在宏調(diào)用中,有時實參使用的是字符串(不是單引號括起來的),而是字符串中包含間隔符(如空格、逗號等),為使間隔符成為實參的一部分,則要用尖括號將字符串括起來作為一個實參的整體來替換形參。例9.6在數(shù)據(jù)段中定義40個字節(jié)的存儲空間。

defdbmacrobuf,xbufxendmdatasegmentdefdbarray,<db40dup(?)>dataends…宏展開為:

1arraydb40dup(?)

9.1.5連接操作符&用連接操作符&可連接實參,形成一個完整的符號或字符串。例9.7用操作符&連接實參,生成指令中的操作碼。宏定義:shiftMACROrig,m,n movcl,n

s&mrig,cl

ENDMshiftMACROrig,m,n

movcl,n

s&mrig,cl

ENDM宏調(diào)用:shiftax,hl,4shiftdx,hr,2宏展開:1movcl,41shlax,cl1movcl,21shrdx,cl例9.8用操作符&連接實參,生成指令中的操作數(shù)。宏定義:studentmacrorec,n,name,tel recdb&n rec1db‘&name&,&tel’ rec2db‘&computer’ endmstudentmacrorec,n,name,tel

recdb&n

rec1db‘&name&,&tel’

rec2db‘&computer’

endm宏調(diào)用:

studentmsg,1,wang,12345678宏展開:1msgdb11rec1db‘wang,12345678’ 1rec2db‘&computer’

9.1.6宏替換操作符%宏替換:匯編程序把跟在%后的表達式的值轉(zhuǎn)換為當前基數(shù)下的數(shù),在展開期間用這個數(shù)來取代形參(啞元)。格式:%表達式例9.9用操作符%將實參的值替換形參。宏定義: studentmacrorec,n,msg rec&ndbmsg endm宏調(diào)用: n=1 studentnumb,%n,‘wang,12345678’ n=n+1 studentnumb,%n,‘zhou,56781234’9.1.7LOCAL偽操作在宏定義中,常常使用標號,當多次宏調(diào)用后,就會出現(xiàn)標號重復定義的錯誤。顯然在程序中多次調(diào)用該宏定義時,則展開后會出現(xiàn)標號的多次重復定義,這是不允許的。為此,系統(tǒng)提供了LOCAL偽操作。例9.10宏定義體中使用標號。錯誤形式宏定義: cmpdatamacror1,r2,max cmpr1,r2 jgemr1 movmax,r2 jmpmr2 mr1:movmax,r1 mr2: endm宏調(diào)用: cmpdataax,bx,var cmpdatadx,cx,valueLOCAL偽操作格式:LOCAL符號[,符號]匯編程序?qū)OCAL偽操作定義的符號說明為局部標號,對每一個局部標號建立唯一的符號(用??0000~??FFFF)來代替每個局部標號。注意:LOCAL偽操作只能用在宏定義體內(nèi),而且必須是MACRO偽操作后的第一個語句。正確形式宏定義: cmpdatamacror1,r2,max localmr1,mr2 cmpr1,r2 jgemr1 movmax,r2 jmpmr2mr1:movmax,r1 mr2: endm宏調(diào)用: cmpdataax,bx,var cmpdatadx,cx,value宏展開:1cmpax,bx1jge??00001movvar,r21jmp??00011??0000:movvar,r11??0001:1cmpdx,cx1jge??00021movvar,r21jmp??00031??0002:movvar,r11??0003:9.1.8使用宏庫文件如果程序中定義了多個宏,用戶可以把它們集中建立在一個獨立的宏庫文件中。宏庫文件為文本文件,擴展名可為MAC。用INCLUDE偽指令加入宏庫文件,格式:INCLUDE宏庫文件名宏庫文件和當前源程序中定義的標識符不能重復。例9.11宏庫文件STDIO.MAC是關于輸入/輸出的文件。內(nèi)容如下: crequ13 lfequ10 getcharmacro movah,1 int21h endm putcharmacroasc movah,2 movdl,asc int21h endm printsmacromsg movah,9 movdx,offsetmsg int21h endm inputsmacroconbuf movah,10 movdx,offsetconbuf int21h endm crlfmacro putcharcr putcharlf endm exitmacro movah,4ch int21h endm例9.12在程序中加入宏庫文件STDIO.MAC,并使用其中的宏指令。程序內(nèi)容如下: includestdio.mac datasegment stringdb16,?,16dup(?) msgboxdb‘輸入字符串請用$結束’,13,10,‘$’ dataends codesegmentassumecs:code,ds:data start: getchar;輸入一個字符 crlf;輸出回車換行 putchar‘a(chǎn)’;輸出一個字符 crlf;輸出回車換行 inputsstring;輸入字符串 crlf;輸出回車換行 printsstring+2;輸出字符串 exit;退出程序codeends endstart下列程序是在3個數(shù)中找出最小的數(shù)并放入al,在括號中填入指令使其完整。

mov

al,x

mov

bl,y

mov

cl,z

cmp

al,bl (1)

(2)

l1:cmpal,cl(3)(4)

l2:ret空1的答案jll1xchgal,blxchgal,cljlel2ABCD提交單選題10分空2的答案jll1xchgal,blxchgal,cljlel2ABCD提交單選題10分空3的答案jll1xchgal,blxchgal,cljlel2ABCD提交單選題10分空4的答案jll1xchgal,blxchgal,cljlel2ABCD提交單選題10分數(shù)據(jù)段如下:datasegmentda1 db 1,2,‘a(chǎn)bcd’

count=$-da1da2db9dup(?)dataends補充括號處的指令,使得程序把DA1數(shù)據(jù)區(qū)數(shù)據(jù)移到DA2數(shù)據(jù)區(qū)。mov ax,data

movds,axmov

es,(5)mov cx,(6)

mov

si,(7)

movdi,(8)(9)

(10)空5的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分空6的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分空7的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分空8的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分空9的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分空10的答案OFFSETDA1AXCOUNTOFFSETDA2ABCD提交REPMOVSBECLDF單選題10分9.2其它高級偽操作9.2.1PURGE偽操作一個宏定義可以用PURGE偽操作來取消,然后可以再重新定義。格式:PURGE宏指令名[,宏指令名]取消宏定義的作用是使該宏定義成為空,如果程序中對已被取消宏定義進行宏調(diào)用,匯編程序則忽略該宏調(diào)用,不會進行宏展開。9.2.2列表偽操作列表偽操作可以控制其后的宏調(diào)用是否在列表文件中出現(xiàn)宏展開,并不影響宏展開的實際產(chǎn)生。.LISTMACRO\XALL:列出產(chǎn)生目標碼的宏展開,默認情況。.LISTMACROALL\LALL:列出包括注釋在內(nèi)的所有宏展開。.NOLISTMACRO\SALL:不列出任何宏展開。9.2.3重復匯編有時程序中,需要得到連續(xù)相同的或者格式相同的一組代碼,這時可使用重復匯編。1.重復偽操作格式:REPT表達式

…(重復塊)

ENDM表達式的值表示重復塊的重復次數(shù)。

例9.13在數(shù)據(jù)段產(chǎn)生字節(jié)數(shù)據(jù),首地址為ARRAY。宏定義: X=0 ARRAYLABELBYTE REPT99 DBX X=X+1 ENDM匯編后產(chǎn)生: 1DB0 1DB1 1DB2… 1DB98例9.14在代碼段產(chǎn)生一組代碼,該組代碼的功能是從鍵盤輸入9個字符,放入數(shù)組ARRAY中。程序如下: n=0 rept9 getcharmovarray+n,aln=n+1endmmovah,4chint21hcodeendsendstart

getcharmacro movah,1 int21hendmdatasegmentarraydb10dup(?)dataendscodesegmentassumecs:code,ds:datastart:movax,data

movds,ax重復匯編中使用了宏調(diào)用,這部分經(jīng)匯編后產(chǎn)生: 2movah,1 2int21h 1movarray+n,al 1n=n+1 2movah,1 2int21h 1movarray+n,al 1

溫馨提示

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

最新文檔

評論

0/150

提交評論