模塊化程序設(shè)計(jì)_第1頁(yè)
模塊化程序設(shè)計(jì)_第2頁(yè)
模塊化程序設(shè)計(jì)_第3頁(yè)
模塊化程序設(shè)計(jì)_第4頁(yè)
模塊化程序設(shè)計(jì)_第5頁(yè)
已閱讀5頁(yè),還剩59頁(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)介

1、第14章 模塊化程序設(shè)計(jì) 14.1 段間調(diào)用 14.2 定義外部標(biāo)識(shí)符偽指令 14.3 使用EXTRN和PUBLIC的范例 14.4 在指令段使用PUBLIC 14.5 在數(shù)據(jù)段使用PUBLIC 14.6 參數(shù)傳送 14.7 C語(yǔ)言與匯編語(yǔ)言的鏈接 14.1 段 間 調(diào) 用 前面介紹的CALL 指令都是段內(nèi)的調(diào)用,即在同一個(gè)指令段內(nèi)。段內(nèi)調(diào)用的CALL指令范圍為0000HFFFFH。一條段內(nèi)調(diào)用指令(CALL) 的目的碼是3個(gè)字節(jié)長(zhǎng)度,例如: E8 2000 (0020) ;十六進(jìn)制 十六進(jìn)制E8是段內(nèi)調(diào)用指令(CALL)機(jī)器指令的操作碼,其操作是先把當(dāng)前IP指令指針寄存器的值壓入堆棧保存,這

2、個(gè)值是CALL的下一條指令地址;然后,再把被調(diào)用的子程序的偏移地址(2000逆序)值送入IP 寄存器,IP0020。微處理器把當(dāng)前CS的值和IP的值相結(jié)合形成物理地址,此地址指向被調(diào)用子程序的第1字節(jié)。當(dāng)子程序的執(zhí)行中,遇到RET指令離開子程序返回時(shí),RET指令會(huì)從堆棧中彈出IP的保留值,并把它裝入IP,使程序返回到CALL的下一條指令繼續(xù)執(zhí)行,這個(gè)過程是段內(nèi)調(diào)用。 其特點(diǎn)是在子程序調(diào)用、返回過程中段寄存器CS不變化,只有指令指針寄存器IP發(fā)生變化。主程序與被調(diào)用的子程序同在一個(gè)段內(nèi)。 模塊化程序設(shè)計(jì)必然涉及到模塊間的調(diào)用問題。模塊間的調(diào)用是通過段間的調(diào)用來(lái)實(shí)現(xiàn)的。若被調(diào)用的子程序是在現(xiàn)指令段

3、之外,則稱為段間調(diào)用。一條段間調(diào)用指令(CALL)的機(jī)器指令碼共有5個(gè)字節(jié)。例如: 9A 0002 AF04 (04AF 0200) ;十六進(jìn)制 十六進(jìn)制9A是段間調(diào)用指令(CALL)機(jī)器指令的操作碼。操作是:首先將CS段寄存器的值壓入堆棧,并把被調(diào)用子程序所在段的段值(AF04逆序)裝入CS段寄存器,CS04AF;然后把IP指令指針寄存器的值壓入堆棧,并將被調(diào)用子程序相應(yīng)的偏移地址(0002逆序)裝入IP,IP0200。 這些操作建立了被調(diào)用子程序的第一條待執(zhí)行指令的地址: 十六進(jìn)制 段 值: CS 04AF0 偏移地址: IP + 0200 物理地址: 04CF0 當(dāng)離開子程序返回時(shí),段間

4、調(diào)用的RET指令會(huì)從堆棧中依序彈出IP和CS兩個(gè)寄存器的原值,返回到CALL的下一條指令。其特點(diǎn)是在子程序調(diào)用、返回過程中,段寄存器CS和指令指針寄存器IP均發(fā)生變化。主程序與被調(diào)用的子程序不在同一個(gè)段內(nèi)。 14.2 定義外部標(biāo)識(shí)符偽指令 當(dāng)進(jìn)行模塊化程序設(shè)計(jì)時(shí),首先應(yīng)考慮的問題是模塊間控制的耦合和數(shù)據(jù)的耦合??刂岂詈暇褪悄K在怎樣的環(huán)境下如何進(jìn)入又如何退出。數(shù)據(jù)耦合就是諸模塊間如何進(jìn)行數(shù)據(jù)通訊。例如,有一個(gè)主模塊(MAINPROG)調(diào)用一個(gè)子模塊(SUBPROG),它要用到一個(gè)段間調(diào)用(CALL),如圖14-1所示。 EXTRN SUBPROG:FARMAINPROG: CALL SUBPR

5、OG PUBLIC SUBPROGSUBPROG: RET圖14-1 段間調(diào)用 主模塊MAINPROG內(nèi)的CALL指令,必須知道子模塊SUBPROG是位于本段之外的標(biāo)號(hào)。否則匯編過程中會(huì)產(chǎn)生一個(gè)錯(cuò)誤信息指出SUBPROG是一個(gè)未定義的符號(hào)。EXTRN偽指令就是執(zhí)行此功能的,它告訴匯編程序SUBPROG是一個(gè)遠(yuǎn)程的標(biāo)號(hào)(FAR Label),是定義在另一個(gè)模塊里的。因?yàn)閰R編程序無(wú)法知道真是如此,所以就產(chǎn)生“空的”目的操作數(shù)0000,即先空出;而由鏈接程序在鏈接時(shí)再填入確定值。例如(參考例14.4主模塊程序清單): 0011 9A0000-E 子模塊SUBPROG內(nèi)含有一個(gè)PUBLIC偽指令,它告

6、訴匯編程序和鏈接程序,其他模塊需要知道SUBPROG的地址。當(dāng)MAINPROG與SUBPROG都已匯編成目的模塊文件后,它們可以下列的方式來(lái)鏈接: LINK MAINPROG+SUBPROG Run File MAINPROG.EXE: List File NUL.MAP: CON Libraries .LIB: 鏈接程序?qū)⒁粋€(gè)目的模塊內(nèi)的EXTRN匹配上另一個(gè)模塊內(nèi)的PUBLIC,并將插入所有需要的偏移地址,然后把兩個(gè)目的模塊組合成一個(gè)可執(zhí)行的文件。若有不匹配的情況,鏈接程序會(huì)給出錯(cuò)誤信息。 利用EXTRN和PUBLIC這兩條偽指令,一個(gè)模塊可以訪問其他模塊的標(biāo)識(shí)符(變量或者標(biāo)號(hào))。如果一個(gè)

7、標(biāo)識(shí)符只在這一個(gè)模塊中定義過,那么它相對(duì)這個(gè)模塊就是一個(gè)內(nèi)部的標(biāo)識(shí)符或局部標(biāo)識(shí)符。如果它沒有在這一個(gè)模塊中定義過,而是在其他一個(gè)模塊中定義過,那么它相對(duì)于該模塊就稱為外部標(biāo)識(shí)符。 對(duì)于只產(chǎn)生一個(gè)單一目標(biāo)模塊的匯編語(yǔ)言程序而言,它所訪問的所有標(biāo)識(shí)符必須是局部(內(nèi)部)定義的,否則就會(huì)產(chǎn)生一個(gè)錯(cuò)誤信息匯編程序會(huì)查出有一個(gè)未定義的標(biāo)識(shí)符(標(biāo)號(hào)或變量)存在。對(duì)于多模塊程序來(lái)說(shuō),必須給匯編程序一個(gè)信息以說(shuō)明其間的有些標(biāo)識(shí)符是外部的,而不至于匯編程序把它們理解為一些無(wú)效的標(biāo)識(shí)符。此外為了允許其他模塊訪問本給定模塊中的標(biāo)識(shí)符,該給定模塊必須包含一個(gè)標(biāo)識(shí)符清單,以說(shuō)明其中的標(biāo)識(shí)符可以讓其他模塊訪問。因此,每個(gè)模

8、塊可含有(不一定絕對(duì)含有)兩個(gè)清單,一個(gè)清單表明它所訪問其他模塊的外部標(biāo)識(shí)符(EXTRN),而另一個(gè)則列出它所定義的且讓其他模塊訪問的標(biāo)識(shí)符(PUBLIC); 這兩個(gè)清單靠EXTRN和PUBLIC這兩條偽指令來(lái)列出。 EXTRN和PUBLIC偽指令的格式如下: EXTRN 標(biāo)識(shí)符:類型, PUBLIC 標(biāo)識(shí)符, EXTRN偽指令里的標(biāo)識(shí)符是被申明的外部的變量或標(biāo)號(hào),而PUBLIC偽指令里的標(biāo)識(shí)符是供其他模塊使用的變量或標(biāo)號(hào)。由于在產(chǎn)生相應(yīng)的機(jī)器代碼之前,匯編語(yǔ)言必須要知道所有標(biāo)識(shí)符的類型,以便確定指令的字節(jié)數(shù)(長(zhǎng)度),故在EXTRN偽指令里的每一個(gè)標(biāo)識(shí)符都伴有類型符出現(xiàn)。 對(duì)于變量來(lái)說(shuō),類型有

9、BYTE、WORD、DWORD等,對(duì)于標(biāo)號(hào)來(lái)說(shuō)類型則有NEAR或FAR。注意:標(biāo)識(shí)符可以是變量、符號(hào)常量、標(biāo)號(hào)和過程名。 例如:INC VAR1 語(yǔ)句,如果VAR1是外部變量,并且是一字變量,那么在含有這個(gè)語(yǔ)句的模塊中必須使用下列偽指令: EXTRN ,VAR1:WORD 而在定義VAR1的模塊中則一定要有下面的偽指令: PUBLIC ,VAR1 鏈接程序的主要任務(wù)之一,就是檢測(cè)并證實(shí)EXTRN語(yǔ)句里的每一個(gè)標(biāo)識(shí)符是否與PUBLIC語(yǔ)句的標(biāo)識(shí)符相匹配,如果不相匹配,鏈接程序就會(huì)給出出錯(cuò)信息。下面給出三個(gè)模塊,說(shuō)明鏈接程序是怎樣查找匹配,并指出其中錯(cuò)誤。 模塊1:EXTRN VAR2:WORD,

10、LAB2:FARPUBLIC VAR1,LAB1; DATA1 SEGMENT VAR1 DB 2 VAR3 DB ? VAR4 DW ?DATA1 ENDS; LAB1: 模塊2:EXTRN VAR1:BYTE,VAR4:WORDPUBLIC VAR2 鏈接錯(cuò)誤,原因是模塊1中PUBLIC ; 沒有申明匹配 DATA2 SEGMENT VAR2 DW 0 VAR3 DB 5 DUP(?)DATA2 ENDS ; 模塊3:EXTRN LAB1:FARPUBLIC LAB2,LAB3 ; 其他模塊未使用LAB2: 不需申明LAB3: 14.3 使用EXTRN和PUBLIC的范例 下面的例子中含有

11、兩個(gè)模塊:主模塊CALLMUL1和一個(gè)子模塊SUBMUL1。主模塊定義了堆棧段、數(shù)據(jù)段和指令段。數(shù)據(jù)段定義了兩個(gè)數(shù)據(jù)項(xiàng)PRICE和QTY。指令段分別把PRICE和QTY裝入AX和BX寄存器,然后調(diào)用子模塊。主模塊內(nèi)的偽指令EXTRN指明了本模塊使用的外部模塊SUBMUL1。 子模塊內(nèi)有一條偽指令PUBLIC,它告訴鏈接程序SUMUL1是由其他模塊調(diào)用的,同時(shí)指明此處是鏈接的進(jìn)入點(diǎn)。子模塊的功能是把AX寄存器的內(nèi)容乘以BX寄存器的內(nèi)容,所得乘積放入DX:AX這一對(duì)寄存器內(nèi)。 子模塊內(nèi)沒有定義任何數(shù)據(jù),所以它沒有數(shù)據(jù)段;也可以定義數(shù)據(jù)段,但只能在子模塊中使用。 在子模塊內(nèi)也沒有定義堆棧段,它與主模

12、塊共同使用一個(gè)堆棧。所以,在主模塊中定義的堆棧,子模塊也可以使用。鏈接程序要求至少有一個(gè)堆棧段,在主模塊內(nèi)定義的堆棧段就可以滿足要求。例14.1 EXTRN和PUBLIC應(yīng)用。 主模塊程序清單如下:; 主模塊:; EXTRN SUBMUL1:FAR; STACK SEGMENT PARA STACK STACK DW 64 DUP (?)STACK ENDS; DATASGSEGMENT PARA DATAQTY DW 0140HPRICE DW 2500HDATASGENDS; CODESG SEGMENT PARA CODEBEGIN PROC FAR ASSUME CS:CODESG,D

13、S:DATASG,SS:STACKPUSH DS SUB AX,AX PUSH AX MOVAX,DATASG MOV DS,AX MOV AX,PRICE MOV BX,QTY CALL SUBMUL1 RETBEGIN ENDPCODESG ENDS END BEGIN 子模塊程序清單如下:; ;子模塊:CODESG SEGMENT PARA CODESUBMUL1 PROC FAR ASSUME CS:CODESG PUBLIC SUBMUL1 MUL BX RETSUBMUL1 ENDPCODESG ENDS END SUBMUL1主模塊和子模塊分別匯編正確無(wú)誤后,參考上節(jié)內(nèi)容鏈接,產(chǎn)

14、生一個(gè)EXE文件。C:masmLINK CALLMUL1+SUBMUL1Run File CALLMUL1.EXE:Enter(回車)List File NUL.MAP: EnterLibraries .LIB: Enter14.4 在指令段使用PUBLIC 在主模塊的指令段和子模塊的指令段使用PUBLIC偽指令,鏈接程序會(huì)把兩個(gè)邏輯指令區(qū)段結(jié)合成一個(gè)實(shí)際的指令段。在例14.1的主模塊和子模塊中各有一處修改,均是在指令段的SEGMENT偽指令內(nèi)使用PUBLIC,用法如下:COD ESG SEGMENT PARA PUBLIC CODE 例14.2 在指令段使用PUBLIC。主模塊程序清單如下:

15、; 主模塊:; EXTRN SUBMUL:FAR; STACK SEGMENT PARA STACK STACK DW 64 DUP (?)STACK ENDS; DATASGSEGMENT PARA DATAQTY DW 0140HPRICE DW 2500HDATASG ENDS; CODESG SEGMENT PARA PUBLIC CODEBEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACK PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX MOV AX,PRICE MOV BX,QTY

16、CALL SUBMUL RETBEGIN ENDPCODESG ENDS END BEGIN子模塊程序清單如下:; ; 子模塊:CODESG SEGMENT PARA PUBLIC CODESUBMUL PROC FAR ASSUME CS:CODESG PUBLIC SUBMUL MUL BX RETSUBMUL ENDPCODESG ENDS END SUBMUL 當(dāng)兩個(gè)段使用同一個(gè)名稱(CODESG)、同樣的類型(CODE)以及同樣段的組合類型(PUBLIC)時(shí),鏈接程序會(huì)把這樣的兩個(gè)邏輯段組合成一個(gè)實(shí)際的物理指令區(qū)。通過匯編時(shí)產(chǎn)生的LST文件中的符號(hào)表,可以了解到一個(gè)指令段的情況;也可

17、利用DEBUG程序觀察到一個(gè)指令段的情況。14.5 在數(shù)據(jù)段使用PUBLIC 你可能會(huì)有這樣的需求,在一個(gè)模塊內(nèi)要處理另外一個(gè)模塊的數(shù)據(jù)。例如前面的例題中,主模塊仍然定義數(shù)據(jù)PRICE和QTY;但是由子模塊使用它們,把它們的值放入AX和BX。程序修改如下: 例14.3 在數(shù)據(jù)段使用PUBLIC。主模塊程序清單如下:; 主模塊:; EXTRN SUBMUL:FARPUBLIC QTY,PRICE; STACK SEGMENT PARA STACK STACK DW 64 DUP (?)STACK ENDS; DATASGSEGMENT PARA PUBLIC DATAQTY DW 0140HPR

18、ICE DW 2500HDATASGENDS; CODESG SEGMENT PARA PUBLIC CODEBEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACK PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX CALL SUBMUL RETBEGIN ENDPCODESG ENDS END BEGIN 子模塊程序清單如下:; ; 子模塊: EXTRN QTY:WORD,PRICE:WORD; CODESG SEGMENT PARA PUBLIC CODESUBMUL PROC FAR ASSU

19、ME CS:CODESG PUBLIC SUBMUL MOV AX,PRICE MOV BX,QTY MUL BX RETSUBMUL ENDPCODESG ENDS END SUBMULPUBLIC QTY,PRICE ;聲明主模塊的QTY和PRICE為外部引用EXTRN QTY:WORD,PRICE:WORD;聲明QTY 和PRICE是外部標(biāo)識(shí)符 子模塊中使用了主模塊的變量,所以兩個(gè)模塊中都應(yīng)進(jìn)行聲明:14.6 參 數(shù) 傳 送 主模塊調(diào)用子模塊,通常也稱為主程序調(diào)用子程序,主程序經(jīng)常要傳送一些參數(shù)給子程序,子程序運(yùn)行完成后一般都要返回一些信息給主程序。這種主程序和子程序間的信息傳送稱為參數(shù)

20、傳送或過程間的數(shù)據(jù)通信。參數(shù)傳送的方法有三種:(1) 利用寄存器傳遞參數(shù):適用參數(shù)較少時(shí);(2) 利用存儲(chǔ)器傳遞參數(shù):適用參數(shù)較多時(shí);(3) 利用堆棧傳遞參數(shù):適用嵌套、遞歸情況。數(shù)據(jù)傳送根據(jù)范圍可分為以下幾種:(1) 同一個(gè)模塊內(nèi)的段內(nèi)參數(shù)傳送。(2) 同一個(gè)模塊內(nèi)的段間參數(shù)傳送。(3) 不同模塊間的參數(shù)傳送。(4) 不同語(yǔ)言間的參數(shù)傳送 例14.4 利用堆棧傳送參數(shù)。 主模塊程序清單如下:; 主模塊:; EXTRN SUBMUL:FAR ; 0000STACK SEGMENT PARA STACK STACK 0000 0040 DW 64 DUP (?) ? 0080STACK ENDS

21、 ; 0000DATASGSEGMENT PARA DATA 0000 0140QTY DW 0140H 0002 2500PRICE DW 2500H 0004DATASG ENDS ; 0000CODESG SEGMENT PARA PUBLIC CODE 0000BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACK 0000 1EPUSH DS 0001 2B C0 SUB AX,AX 0003 50 PUSH AX 0004 B8 - RMOV AX,DATASG 0007 8E D8 MOV DS,AX 0009 FF 36 0002

22、R PUSH PRICE 000D FF 36 0000 R PUSH QTY 0011 9A 0000 E CALL SUBMUL 0016 CBRET 0017BEGIN ENDP 0017CODESG ENDS END BEGIN 子模塊程序清單如下:; ;子模塊: 0000CODESG SEGMENT PARA PUBLIC CODE 0000SUBMUL PROC FAR ASSUME CS:CODESG PUBLIC SUBMUL 0000 55PUSH BP 0001 8B ECMOV BP,SP 0003 8B 46 08MOV AX,BP+8 0006 8B 5E 06MOV

23、 BX,BP+6 0009 F7 E3MUL BX 000B 5DPOP BP 000C CA 0004RET 4 000FSUBMUL ENDP 000FCODESG ENDS END 主模塊程序在調(diào)用子模塊程序SUBMUL之前,把 PRICE和 QTY都?jí)喝攵褩!?堆棧的變化如下: 16 00 XX XX 40 01 00 25 00 00 XX XX 6 5 4 3 2 1(1) PUSH DS 將DS中的段地址壓入堆棧。(2) PUSH AX 把偏移地址0壓入堆棧。(3) PUSH PRICE 把2500壓入堆棧。(4) PUSH QTY 把0140壓入堆棧。(5) CALL 把CS寄

24、存器的內(nèi)容壓入堆棧。(6) IP 指令指針寄存器的內(nèi)容0016 也被壓入堆棧。 被調(diào)用的子模塊程序SUBMUL要用BP來(lái)取得堆棧內(nèi)的參數(shù)。它的第一個(gè)操作是把BP的內(nèi)容壓入到堆棧保存起來(lái)。本例中BP的內(nèi)容正好是0,然后把SP的內(nèi)容送入BP。因?yàn)锽P可以作為尋址寄存器,而SP則不行。此操作使BP的值為0072,因?yàn)镾P的初值應(yīng)是堆棧的大小十六進(jìn)制80,每次壓入堆棧一個(gè)字SP減2。堆棧指針的變化應(yīng)是: 00 00 16 00 XX XX 40 01 00 25 00 00 XX XX .SP: 72 74 76 78 7A 7C 7E 80 因?yàn)楝F(xiàn)在BP的內(nèi)容是0072,所以PRICE在BP+8位置

25、,而QTY在BP+6位置。下面兩條指令把這些值分別搬入AX和BX,然后作乘法。要從子模塊程序回到調(diào)用程序時(shí),先恢復(fù)BP的值0000并將SP加2,從72變成74。 最后一條指令RET,是一條子程序返回指令,它執(zhí)行下列操作: (1) 彈出當(dāng)前堆棧頂端的字1600送入IP。 (2) 把SP+2,SP從74增為76。 (3) 取出目前堆棧頂端的字(XXXX),存入CS。 (4) 把SP+2,SP從76增為78。 子程序返回指令帶有參數(shù)即RET 4,指令中的4的作用是保證正確返回,將SP的值加4修正為7C。這是因?yàn)槎褩?nèi)的參數(shù)已不再需要,故予以舍棄。使用堆棧傳送參數(shù)時(shí)應(yīng)特別小心,SP的值弄錯(cuò)的話會(huì)產(chǎn)生預(yù)想不到的結(jié)果。14.7 C語(yǔ)言與匯編語(yǔ)言的鏈接 C語(yǔ)言與匯編語(yǔ)言的鏈接是指C語(yǔ)言與匯編語(yǔ)言的互相調(diào)用。通常只是指從C語(yǔ)言調(diào)用匯編語(yǔ)言程序。這是因?yàn)镃語(yǔ)言不但編程容易,而且效率高。但是,匯編語(yǔ)言效率最高,特別是適合對(duì)硬件的直接控制

溫馨提示

  • 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)論