




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
匯編語(yǔ)言程序設(shè)計(jì)(第2版)第9章模塊化程序設(shè)計(jì)與混合編程
模塊化技術(shù)是大型軟件開發(fā)的基本技術(shù),高、低級(jí)語(yǔ)言間的混合編程是大型軟件常用的另一技術(shù)。本章詳述這兩種技術(shù),應(yīng)重點(diǎn)掌握二個(gè)匯編語(yǔ)言模塊間的代碼調(diào)用與數(shù)據(jù)交換方法,以及編寫能夠被C語(yǔ)言調(diào)用的匯編語(yǔ)言模塊的方法。
9.1模塊化程序設(shè)計(jì)
9.2匯編語(yǔ)言與高級(jí)語(yǔ)言的接口實(shí)訓(xùn)一鍵盤錄入數(shù)據(jù)的轉(zhuǎn)換與顯示實(shí)訓(xùn)二C語(yǔ)言調(diào)用匯編語(yǔ)言子程序進(jìn)行數(shù)據(jù)傳遞與顯示9.1模塊化的程序設(shè)計(jì)9.1.1模塊化設(shè)計(jì)原則9.1.2模塊之間組合與通信9.1.3模塊化設(shè)計(jì)舉例第9章模塊化程序設(shè)計(jì)與混合編程
對(duì)于一個(gè)大而復(fù)雜的任務(wù),我們一般把整個(gè)程序分成若干個(gè)子任務(wù)或模塊,稱為“模塊化程序設(shè)計(jì)”。模塊化設(shè)計(jì)的難題是:如何把程序分成模塊,以及如何再裝配起來(lái)。1.模塊化的優(yōu)點(diǎn)單個(gè)的模塊易于編寫、調(diào)試、修改。一個(gè)模塊可以在多個(gè)地方或多個(gè)程序中使用??梢灾苯永靡延械哪K。多個(gè)程序員可以并行工作。9.1.1模塊化設(shè)計(jì)原則第9章模塊化程序設(shè)計(jì)與混合編程2.模塊化的缺點(diǎn)增加了模塊的劃分工作。模塊的裝配也是難題,尤其是合并多人編寫的程序時(shí)。為調(diào)試一個(gè)模塊,需要額外地為其準(zhǔn)備調(diào)試數(shù)據(jù)、專用程序等
模塊化程序設(shè)計(jì)的關(guān)鍵是模塊的劃分,層次圖和模塊說(shuō)明是模塊劃分的主要描述工具。層次圖是一個(gè)方塊圖,用來(lái)表示模塊與模塊之間的調(diào)用關(guān)系,如圖9-1所示。模塊說(shuō)明是模塊功能的文字描述,應(yīng)簡(jiǎn)要寫出模塊的功能、所用基本算法、入口參數(shù)、出口參數(shù)、所調(diào)用到的其它模塊、調(diào)用注意事項(xiàng)等信息。3.模塊的描述第9章模塊化程序設(shè)計(jì)與混合編程圖9-1層次圖
主控模塊
模塊A
模塊B
模塊C
模塊E
模塊F
模塊G
模塊H
模塊D
第9章模塊化程序設(shè)計(jì)與混合編程4.模塊的劃分原則
模塊的劃分無(wú)固定的規(guī)則,應(yīng)視情況靈活確定,但應(yīng)遵循如下基本原則:
①模塊間的調(diào)用關(guān)系盡可能簡(jiǎn)單。盡量避免從多個(gè)入口點(diǎn)進(jìn)入模塊或從多個(gè)出口點(diǎn)退出,否則模塊不易調(diào)試。
②模塊間的數(shù)據(jù)耦合應(yīng)盡量小,即盡量減少數(shù)據(jù)傳遞,對(duì)于需要傳遞參數(shù)個(gè)數(shù)較多的模塊,可考慮合并成一個(gè)模塊。
③模塊的大小適中,若一個(gè)模塊太大,則編寫調(diào)試因難;若太小,模塊間的調(diào)用、連接開銷則太大,一般一個(gè)模塊長(zhǎng)度在50至500行內(nèi)為宜。返回本章首頁(yè)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程9.1.2模塊之間的組合與通訊
一個(gè)大程序劃分為若干模塊后,各個(gè)模塊分別編寫并匯編成目標(biāo)模塊文件(.OBJ文件),然后由鏈接程序(如LINK.EXE或TLINK.EXE等)將各個(gè)模塊組合在一起,成為一個(gè)可執(zhí)行文件(.EXE文件)。模塊間的組合,主要由鏈接程序完成。一個(gè)模塊中往往有多個(gè)段,多個(gè)模塊則有更多的段,這些段在鏈接時(shí)有的需要合并成一個(gè),有的則需要相互重疊,有的則不與其它段發(fā)生聯(lián)系。要想使鏈接程序按預(yù)想的方案組合各個(gè)段,關(guān)鍵是在各個(gè)模塊編寫前約定好段名、組合類型、定位類型、類別等參數(shù),其中組合類型指定各個(gè)模塊間的同名段該如何處理(各自獨(dú)立?相互合并?相互重疊?),而定位類型決定段的地址要求,它關(guān)系到段間是否留有空隙的問題,類別則會(huì)導(dǎo)至調(diào)整段的先后次序。其中主要的參數(shù)是組合類型。
返回本章首頁(yè)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程
由于各個(gè)模塊被單獨(dú)匯編,所以A模塊要想調(diào)用B模塊內(nèi)定義的符號(hào)(變量、過程等),那么A模塊必須通知匯編程序指定的符號(hào)在別的模塊內(nèi),否則匯編時(shí)會(huì)出錯(cuò)。另外,B模塊內(nèi)也必須通知匯編程序某個(gè)符號(hào)將被其它模塊調(diào)用,否則匯編程序不會(huì)把它寫入目標(biāo)文件中,最后導(dǎo)致鏈接失敗。第9章模塊化程序設(shè)計(jì)與混合編程9.1.3模塊化設(shè)計(jì)舉例1.模塊間代碼的轉(zhuǎn)移
一個(gè)模塊調(diào)用另一個(gè)模塊的代碼時(shí),若調(diào)用者所在的段與位于另一模塊內(nèi)的被調(diào)用者所在的段鏈接后能合并成一個(gè)段,則調(diào)用相當(dāng)于段內(nèi)調(diào)用,轉(zhuǎn)移采用近轉(zhuǎn)移即可;若不能合并成一個(gè)段,則必須采用遠(yuǎn)轉(zhuǎn)移。第9章模塊化程序設(shè)計(jì)與混合編程【例9.1】某系統(tǒng)由A、B二個(gè)模塊構(gòu)成,A模塊要調(diào)用到B模塊的一個(gè)過程disp,以顯示一個(gè)字符。二個(gè)模塊如下:模塊A:EXTRN DISP:NEAR
.MODEL SMALL
.CODE
START:
CALL DISP
MOV AH,4CH
INT 21H
END START第9章模塊化程序設(shè)計(jì)與混合編程模塊B:PUBLIC DISP
.MODEL SMALL
.CODE
DISP PROC NEAR
MOV DL,'A'
MOV AH,2
INT 21H
RET
DISP ENDP
END第9章模塊化程序設(shè)計(jì)與混合編程
假設(shè)模塊A存盤后文件名為A.ASM,模塊B存盤后文件名為B.ASM,則可用以下命令行分別匯編,然后鏈接合并。
MASMA;
MASMB;
LINKA+B;
最后得到可執(zhí)行文件A.EXE。執(zhí)行該文件,可在屏幕上顯示字符A。
在這個(gè)例子中,兩個(gè)模塊存儲(chǔ)模式相同,并且都是用.CODE偽指令指定代碼段,則二個(gè)模塊內(nèi)代碼段的段名、定位類型、組合類型、類別等都由匯編程序自動(dòng)生成(分別為:TEXT、WORD、PUBLIC、‘CODE’),由于二個(gè)段是同名段,且都為PUBLIC組合類型,故鏈接程序最后將其合并為一個(gè)段,因而模塊A對(duì)模塊B內(nèi)disp的調(diào)用為段內(nèi)調(diào)用。第9章模塊化程序設(shè)計(jì)與混合編程【例9.2】段間調(diào)用。對(duì)例9-1中的二個(gè)模塊作如下修改:EXTRN DISP:FAR
.MODEL SMALL
.CODE
START:
CALL DISP MOV AH,4CH INT 21H END START模塊A:模塊B:PUBLIC DISP
CODE SEGMENT
ASSUME CS:CODE
DISP PROC FAR
MOV DL,'A'
MOV AH,2
INT 21H
RET
DISP ENDP
END第9章模塊化程序設(shè)計(jì)與混合編程
在這個(gè)例子中,由于模塊B中代碼段的段名與模塊A中的不再一致,故二個(gè)段是各自獨(dú)立的代碼段,調(diào)用成為段間調(diào)用,disp不論在模塊A中的外部符號(hào)聲明還是在模塊B中的類型定義,都必須為FAR類型。第9章模塊化程序設(shè)計(jì)與混合編程2.模塊間數(shù)據(jù)的訪問
兩個(gè)模塊之間若要相互交換數(shù)據(jù),可用如下幾種辦法實(shí)現(xiàn):
a.通過寄存器傳遞
b.通過堆棧傳遞
c.互訪對(duì)方變量或數(shù)據(jù)區(qū)
a、b二種方法較為簡(jiǎn)單,因?yàn)椴徽撛谕荒K內(nèi)的各個(gè)過程間,還是在不同模塊內(nèi)的各個(gè)過程間,都中在共用相同的CPU寄存器和堆棧段,所以這種況下調(diào)用在模塊內(nèi)還是在模塊外情況并無(wú)差別。下面主要討論模塊間互訪對(duì)方變量或數(shù)據(jù)區(qū)的方法。第9章模塊化程序設(shè)計(jì)與混合編程3.模塊間互訪對(duì)方變量或數(shù)據(jù)區(qū)的方法
一個(gè)模塊要訪問另一個(gè)模塊內(nèi)的數(shù)據(jù),關(guān)鍵是調(diào)整數(shù)據(jù)段寄存器使之存儲(chǔ)被訪問數(shù)據(jù)所在段的段地址。【例9.3】演示一個(gè)模塊內(nèi)訪問另一模塊內(nèi)變量或數(shù)據(jù)區(qū)的方法。
某工程由如下二個(gè)模塊組成。第9章模塊化程序設(shè)計(jì)與混合編程模塊A:EXTRN SET:FAR
PUBLIC BUF1
.MODEL SMALL
.DATA
BUF1 DB 3
.CODE
START:
MOV AX,@DATA
MOV DS,AX
CALL SET
MOV DL,BUF1
MOV AH,2
INT 21H
MOV AH,4CH
INT 21H
END START第9章模塊化程序設(shè)計(jì)與混合編程模塊B:EXTRN BUF1:BYTE
PUBLIC SET
CODE SEGMENT
ASSUMECS:CODE
SET PROC FAR
MOV BUF1,'8'
RET
SET ENDP
CODE ENDS
END
在這個(gè)例子中,當(dāng)控制從模塊A轉(zhuǎn)到模塊B后,DS寄存器仍指向模塊A的數(shù)據(jù)段,所以模塊B中可用DS直接訪問模塊A中的數(shù)據(jù),這種情況相當(dāng)于在一個(gè)模塊中有二個(gè)代碼段一個(gè)數(shù)據(jù)段的情況,不論控制在哪個(gè)代碼段內(nèi),都可直接訪問數(shù)據(jù)段。第9章模塊化程序設(shè)計(jì)與混合編程【例9.4】二個(gè)模塊都有自己的數(shù)據(jù)段時(shí)從一個(gè)模塊訪問另一個(gè)模塊數(shù)據(jù)區(qū)的方法。對(duì)例9.3進(jìn)行修改如下:EXTRN SET:FAR
PUBLIC BUF1
.MODEL SMALL
.DATA
BUF1 DB 3
.CODE
START:
MOV AX,@DATA
MOV DS,AX
CALL SET
MOV DL,BUF1
MOV AH,2
INT 21H
MOV AH,4CH
INT 21H
END START模塊A:第9章模塊化程序設(shè)計(jì)與混合編程模塊B:EXTRN BUF1:BYTE
PUBLIC SET
DATA SEGMENT
BUF2 DB '5'
DATA ENDS
CODE SEGMENT
ASSUMECS:CODE,DS:DATA
SET PROC FAR
PUSH DS
MOV AX,DATA
MOV DS,AX
MOV BL,BUF2
MOV AX,SEGBUF1
MOV DS,AX
MOV AL,BUF1
ADD AL,BL
MOV BUF1,AL
POP DS
RET
SET ENDP
CODE ENDS
END運(yùn)行顯示:8第9章模塊化程序設(shè)計(jì)與混合編程
這個(gè)例子中模塊A與模塊B各有自已的數(shù)據(jù)段,當(dāng)控制從模塊A轉(zhuǎn)移到模塊B時(shí),DS仍指向模塊A的數(shù)據(jù)段,由于模塊B要使用DS訪問自已的數(shù)據(jù)段,所以它先將DS壓棧保存,然后使DS指向自己的數(shù)據(jù)段,完成數(shù)據(jù)的讀取后,又修改DS使之指向模塊A的數(shù)據(jù)段,從而訪問模塊A的BUF1變量。最后,在返回模塊A前通過出棧將DS恢復(fù)為進(jìn)入時(shí)的初值(本例中由于在訪問模塊A的變量BUF1時(shí)已使DS指向了模塊A的數(shù)據(jù)段,保存恢復(fù)DS的工作可以省略)。
這個(gè)例子的關(guān)鍵是訪問外部模塊的變量前事先要調(diào)整DS使之保存外部變量所在段的段地址。由于訪問內(nèi)存并不一定非要用DS,若用其它段寄存器(如ES),則除了要事先調(diào)整該段寄存器使之存儲(chǔ)被訪問外部變量所在段的段值外,還要在使用變量時(shí)在前面加上段超越標(biāo)記,如可將模塊B修改如下:第9章模塊化程序設(shè)計(jì)與混合編程EXTRN BUF1:BYTE
PUBLIC SET
DATA SEGMENT
BUF2 DB '5'
DATA ENDS
CODE SEGMENT
ASSUMECS:CODE,DS:DATA
SET PROC FAR
PUSH DS
MOV AX,DATA
MOV DS,AX
MOV BL,BUF2
MOV AX,SEGBUF1
MOV ES,AX
MOV AL,ES:BUF1 ;使用段超越標(biāo)記
ADD AL,BL
MOV ES:BUF1,AL
POP DS
RET
SET ENDP
CODE ENDS
END第9章模塊化程序設(shè)計(jì)與混合編程
模塊間信息傳遞的另一個(gè)方法是利用COMMON段,只要二個(gè)模塊中都定義一個(gè)同名同類別的數(shù)據(jù)段,且組合類型都為COMMON,由于這二個(gè)段在鏈接時(shí)要重合為一個(gè)段,只要在這二個(gè)段內(nèi)將變量安排在相同的位置上,那么它們對(duì)應(yīng)的是相同的存儲(chǔ)區(qū)?!纠?.5】 利用COMMON段訪問另一個(gè)模塊的數(shù)據(jù)區(qū)。
將上例進(jìn)行修改,如下:第9章模塊化程序設(shè)計(jì)與混合編程模塊A:EXTRN SET:FAR
DATA SEGMENT COMMON
BUF1 DB 3
BUF2 DB '0'
DATA ENDS
CODE1SEGMENT
ASSUME CS:CODE1,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
CALL SET
MOV DL,BUF2
MOV AH,2
INT 21H
MOV AH,4CH
INT 21H
CODE1 ENDS
END START第9章模塊化程序設(shè)計(jì)與混合編程模塊B:PUBLIC SET
DATA SEGMENT
BUF1 DB ?
BUF2 DB ?
DATA ENDS
CODE2SEGMENT
ASSUME CS:CODE2,DS:DATA
SET PROC FAR
MOV AL,BUF1
ADD BUF2,AL
RET
SET ENDP
CODE2 ENDS
END返回本章首頁(yè)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程9.2匯編語(yǔ)言與高級(jí)語(yǔ)言的接口9.2.1概述9.2.2嵌入式匯編9.2.3匯編語(yǔ)言與C語(yǔ)言的接口第9章模塊化程序設(shè)計(jì)與混合編程9.2.1概述
對(duì)于一項(xiàng)軟件工程而言,首要目標(biāo)是保證達(dá)到軟件所需質(zhì)量,其次是盡可能降低開發(fā)成本。匯編語(yǔ)言與高級(jí)語(yǔ)言在語(yǔ)言表達(dá)能力、表達(dá)的方便程度、編程效率和運(yùn)行效率方面各有特點(diǎn),這就需要它們相互“取長(zhǎng)補(bǔ)短”,即混合編程,以便取得最大的綜合效益。高級(jí)語(yǔ)言與匯編語(yǔ)言的混合編程通常發(fā)生在下列情況下:
①需要訪問機(jī)器的硬件特征,這些特征用高級(jí)語(yǔ)言表達(dá)比較困難。
②某些程序段需要頻煩運(yùn)行,單次運(yùn)行速度的提高可顯著提高整個(gè)系統(tǒng)運(yùn)行效率。
③有現(xiàn)成的匯編語(yǔ)言程序段可用。第9章模塊化程序設(shè)計(jì)與混合編程
高級(jí)語(yǔ)言種類較多,本章主要討論與C語(yǔ)言的混合編程問題,流行的C編譯器主要有TurboC和MSC,本書主要以TurboC為例。
C語(yǔ)言的目標(biāo)是追求效率,因而它與匯編語(yǔ)言與較多的“血源關(guān)系”。C語(yǔ)言提供了三種調(diào)用匯編語(yǔ)言功能的方法:(1)嵌入?yún)R編(2)寄存器偽變量與bdos()、intdos()、int86()等系列DOS、BIOS服務(wù)調(diào)用函數(shù)(3)C語(yǔ)言與匯編語(yǔ)言的混合編程。其中第二種方法因主要涉及C語(yǔ)言的編程問題,本書不作討論,請(qǐng)讀者參考相關(guān)C語(yǔ)言書籍。返回本章首頁(yè)返回上一節(jié)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程9.2.2嵌入式匯編
在C程序中可以直接插入?yún)R編語(yǔ)言語(yǔ)句,稱為嵌入式匯編。1.嵌入式匯編語(yǔ)句的格式asm[<標(biāo)號(hào)>]<匯編指令或偽指令><參數(shù)><;或新行>說(shuō)明:asm
是嵌入?yún)R編語(yǔ)句的關(guān)鍵字
<匯編指令或偽指令>可是任何有效的匯編指令或偽指令<標(biāo)號(hào)>是可選的。
<參數(shù)>是匯編指令或偽指令的操作數(shù),它可引用C語(yǔ)言中的常量、變量和標(biāo)號(hào)。<;或新行>都表示asm語(yǔ)句的結(jié)束,一行內(nèi)可寫多條嵌入式匯編語(yǔ)句,它們以“;”分隔。一行內(nèi)如果只有一個(gè)asm語(yǔ)句,則后面不需要“;”,asm
語(yǔ)句是C語(yǔ)言中唯一的依靠換行的語(yǔ)句。
asm語(yǔ)句如需要注釋,必須采用C格式的注釋,即“/*注釋內(nèi)容*/”
編譯后,函數(shù)外的匯編語(yǔ)句放在數(shù)據(jù)段內(nèi),函數(shù)內(nèi)的匯編語(yǔ)句放在代碼段內(nèi)。第9章模塊化程序設(shè)計(jì)與混合編程2.嵌入式匯編的編譯連接
含有嵌入式匯編的程序不能在TurboC集成開發(fā)環(huán)境下進(jìn)行編譯,因?yàn)榧砷_發(fā)環(huán)境不支持這一功能。這樣的程序必須使用TurboC的命令行編譯器TCC.EXE進(jìn)行編譯,而TCC.EXE在編譯是又要調(diào)用TASM.EXE,所以當(dāng)前目錄下必須保證有匯編程序TASM.EXE。TCC.EXE調(diào)用格式為:
其中file[s]需要編譯或連接的文件,可有一個(gè)或多個(gè)。[options]為各個(gè)參數(shù)選項(xiàng),常用的有“-B”用于指示源程序中使用了嵌入?yún)R編,“–S”能使TCC.EXE編譯成匯編語(yǔ)言的源程序輸出。若程序中使用了嵌入?yún)R編,調(diào)用TCC時(shí)必須選擇-B參數(shù),或者是在程序中使用偽指令“#pragmainline”,此偽指令功能與“-B”參數(shù)等效。TCC[options]file[s]第9章模塊化程序設(shè)計(jì)與混合編程【例9.6】嵌入式匯編的編譯連接
有如下程序:
asmBUFDB“thisisatest $”
main()
{
asm MOV AH,9
asm MOV DX,OFFSET BUF
asm INT 21H
}
在TC的集成開發(fā)環(huán)境下編輯完以上程序后,存盤(假設(shè)文件名為test.c),然后以如下命令行進(jìn)行編譯連接:
tcc–Btest.c.
(注意:tcc的參數(shù)是區(qū)分大小寫的,不要將“-B”寫成“-b”)
則可生成test.exe文件,在DOS下運(yùn)行之,即可在屏幕上顯示“thisisatest”。第9章模塊化程序設(shè)計(jì)與混合編程【例9.7】從嵌入?yún)R編語(yǔ)句中訪問C定義的局部及全局變量。分析如下程序:#include <stdio.h>
int i=3;
main()
{
char j='a';
struct s{
int x;
int y;
}stru;
stru.x=50;
stru.y=20;
printf("\nj=%c", j);
asm inc byte ptr j
printf("\nj=%c", j);
printf("\ni=%d", i);
asm
mov ax,stru.x
asm sub ax,stru.y
asm
mov i,ax
printf("\ni=%d", i);
}該程序的運(yùn)行結(jié)果如下:j=aj=bi=3i=30第9章模塊化程序設(shè)計(jì)與混合編程3.嵌入?yún)R編的限制
嵌入?yún)R編碼中的轉(zhuǎn)移指令只能引用C中定義的標(biāo)號(hào),而嵌入?yún)R編碼中的非轉(zhuǎn)移指令則可引用除標(biāo)號(hào)以外的任何C元素。
在嵌入?yún)R編碼的末尾,下列寄存器的值必須與進(jìn)入嵌入?yún)R編碼時(shí)的值保持一致:BP、SP、CS、DS、SS。如果C程序中用到了寄存器變量,還需再保證SI、DI的值不變,其它寄存器的值可自由改變。返回本章首頁(yè)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程9.2.3匯編語(yǔ)言與C語(yǔ)言的混合編程1.調(diào)用約定
在混合編程中,雙方在如下方面必須遵循相同的接口約定,才可使雙方的代碼協(xié)同工作。①內(nèi)存模式:
即對(duì)內(nèi)存的使用,主要是段、組的劃分,以及段名、組名的約定等。若二種語(yǔ)言對(duì)段的劃分情況不同,則雙方指針或地址的使用便不同,這時(shí)極易發(fā)生運(yùn)行錯(cuò)誤。如在函數(shù)調(diào)用中,一方將四節(jié)地址壓棧,而另一方則只將二字節(jié)地址出棧,可能造成程序崩潰。②命名約定:即標(biāo)識(shí)符的命名規(guī)則,以及是否區(qū)分大小寫等。③調(diào)用約定:
調(diào)用者以什么順序?qū)?shù)壓棧,被調(diào)用者以什么順序提取參數(shù),由誰(shuí)負(fù)責(zé)最后清除堆棧中的參數(shù)等。④參數(shù)傳遞約定:
調(diào)用參數(shù)以什么方式傳遞的,例如傳遞的是參數(shù)的值還是參數(shù)的地址等。第9章模塊化程序設(shè)計(jì)與混合編程2.TucboC的六種存儲(chǔ)模式
為允許程序員決定內(nèi)存布局結(jié)構(gòu),以便更合理高效地使用內(nèi)存,TucboC提供了六種存儲(chǔ)模式(MSC相同),如下:①極小模式:
程序的所有代碼和數(shù)據(jù)限制在64K內(nèi),即程序只有一個(gè)段,CS=DS=ES=SS,所有指針全部為near指針。②小模式:
代碼和數(shù)據(jù)各占一個(gè)段,因而代碼和數(shù)據(jù)分別不能超過64K。DS=SS=ES,所有指針都為near指針。③中模式:
代碼段用far指針,數(shù)據(jù)段用near指針,代碼段可多達(dá)1M,數(shù)據(jù)不能超過64K。④緊湊模式:
數(shù)據(jù)段用far指針,代碼段用near指針。代碼最多64K,數(shù)據(jù)可多達(dá)1M。⑤大模式:
代碼、數(shù)據(jù)均用far指針,因而均可多達(dá)1M。⑥極大模式:
代碼、數(shù)據(jù)均用far指針。TurboC一般限制靜態(tài)數(shù)據(jù)為64K,極大模式下可打破此限制。第9章模塊化程序設(shè)計(jì)與混合編程3.TurboC的調(diào)用約定
為了解TurboC的調(diào)用接口機(jī)制,觀察其以匯編形式給出的編譯結(jié)果是最好的方式。假設(shè)有如下C程序:#include <stdio.h>
int para1=10 ;
int para2;
int
add(int a,int b)
{
return (a+b);
}
main()
{
para1++ ;
para2=add(para1,20);
printf("\n%d\n%d",para1,para2);
}
以上程序,設(shè)存盤后文件名為test.c,則可用如下命令行編譯成匯編語(yǔ)言結(jié)果輸出:TCC -ms -S test.c第9章模塊化程序設(shè)計(jì)與混合編程輸出結(jié)果為(為便于理解,添加了中文注釋):_TEXT segment byte public 'CODE‘ ;代碼段DGROUP group _DATA,_BSS assume cs:_TEXT,ds:DGROUP,ss:DGROUP_TEXT ends_DATA segment word public 'DATA' ;數(shù)據(jù)段_para1 label word
dw 10_DATA ends_TEXT segment byte public 'CODE' ;代碼段; ?debug L5 ;注明以下代碼是由源程序的第5行產(chǎn)生,下同第9章模塊化程序設(shè)計(jì)與混合編程_add proc near ;函數(shù)add
push bp
mov
bp,sp
; ?debug L7
mov ax,word ptr [bp+4] ;取第一個(gè)參數(shù)
add ax,word ptr [bp+6] ;取第二個(gè)參數(shù),并加
;到在AX內(nèi)的第一個(gè)參數(shù)上
jmp short @1
@1:
; ?debug L8
pop bp
ret
_add endp
; ?debug L10第9章模塊化程序設(shè)計(jì)與混合編程_main proc near ;主函數(shù)
; ?debug L12
inc word ptr DGROUP:_para1 ;語(yǔ)句para1++
; ?debug L13
mov ax,20
push ax ;為調(diào)用add壓棧第二個(gè)參數(shù)(最右參數(shù))
push word ptr DGROUP:_para1
;為調(diào)用add壓棧第一個(gè)參數(shù)
call near ptr _add ;調(diào)用add函數(shù)
pop cx
pop cx
;以上兩句清除堆棧中的二個(gè)參數(shù)
mov word ptr DGROUP:_para2,ax ;add返回值在AX
;中,將其賦給para2
; ?debug L 14
push word ptr DGROUP:_para2第9章模塊化程序設(shè)計(jì)與混合編程;為調(diào)用printf壓棧最右參數(shù)
push word ptr DGROUP:_para1
;為調(diào)用printf壓棧第二個(gè)參數(shù)
mov ax,offset DGROUP:s@
push ax ;為調(diào)用printf壓棧第一個(gè)參數(shù)(最左參數(shù))
call near ptr _printf;調(diào)用printf
add sp,6 ;清除堆棧中的三個(gè)參數(shù)
@2:
; ?debug L15
ret
_main endp
_TEXT ends第9章模塊化程序設(shè)計(jì)與混合編程_BSS segment word public 'BSS' ;未初始化的數(shù)據(jù)段
_para2 label word
db 2 dup (?)
_BSS ends
?debug C E9
_DATA segment word public 'DATA’ ;數(shù)據(jù)段
s@ label byte ;定義字符串“\n%d\n%d”
db 10
db 37
db 100
db 10
db 37
db 100
db 0
_DATA ends第9章模塊化程序設(shè)計(jì)與混合編程_TEXT segment byte public 'CODE' ;代碼段
extrn _printf:near
;聲明外部函數(shù)
_TEXT ends
public _main ;聲明公共標(biāo)識(shí)符
public _add
public _para2
public _para1
end第9章模塊化程序設(shè)計(jì)與混合編程說(shuō)明:
(1)匯編模塊要遵循與TurboC一致的內(nèi)存模式,同時(shí)采用TurboC的段名約定,這可用二種方法實(shí)現(xiàn):①使用簡(jiǎn)化的段定義方式,只要用偽指令.MODEL說(shuō)明內(nèi)存模式為SMALL,然后用偽指令.CODE定義代碼段,用偽指令.DATA定義數(shù)據(jù)段,則生成的段名與TurboC的段名一致。②先編寫一個(gè)只有空架的C程序,用TurboC的-B參數(shù)編譯生成匯編輸出,即得到了完整的程序框架。
(2)TurboC在編譯時(shí)會(huì)自動(dòng)在全局變量及函數(shù)名前加上下劃線,如果匯編模塊中的函數(shù)或變量要供TurboC訪問,變量名或函數(shù)名也必須以下劃線開頭。另外C語(yǔ)言大小寫敏感,而匯編語(yǔ)言大小寫不敏感,為不致命名混淆,應(yīng)使匯編語(yǔ)言也保持大小寫敏感,匯編程序的命令行選項(xiàng)/ml(所有符號(hào)區(qū)分大小寫)和/mx(僅公共標(biāo)識(shí)符和外部標(biāo)識(shí)符區(qū)分大小寫)可做到這一點(diǎn)。第9章模塊化程序設(shè)計(jì)與混合編程堆棧頂a.被調(diào)函數(shù)入口處堆棧結(jié)構(gòu)……參數(shù)2參數(shù)1返回地址……SP→堆棧頂b.被調(diào)函數(shù)準(zhǔn)備提取參數(shù)時(shí)的堆棧結(jié)構(gòu)……參數(shù)2參數(shù)1返回地址BP……SP→←BP←BP+2←BP+4←BP+6圖9-2C函數(shù)調(diào)用中的堆棧結(jié)構(gòu)
(3)C語(yǔ)言的參數(shù)均通過堆棧傳遞,且自右向左壓棧。當(dāng)程序進(jìn)入被調(diào)函數(shù)時(shí),堆棧結(jié)果如圖9-2a所示:C語(yǔ)言的被調(diào)函數(shù)是通過BP間址的方式訪問堆棧的,為不破壞BP的值,在使用BP前將其壓棧,這時(shí)各參數(shù)的位置如圖9-2b所示。第9章模塊化程序設(shè)計(jì)與混合編程C語(yǔ)言中基本數(shù)據(jù)類型(char、shortint、int、longint、unsignedint、float、double)以及結(jié)構(gòu)類型的參數(shù)都是以傳值方式傳遞的,而數(shù)組類型的參數(shù)是傳址方式傳遞的,而有些參數(shù)要先進(jìn)行類型轉(zhuǎn)換后再壓棧傳遞(如char先轉(zhuǎn)換為int)?;厩闆r如表9-1所示:
注:若函數(shù)調(diào)用是遠(yuǎn)調(diào)用,則棧頂部的返回地址為4字節(jié),各參數(shù)的偏移值應(yīng)相應(yīng)修改。第9章模塊化程序設(shè)計(jì)與混合編程表9-1C語(yǔ)言參數(shù)的傳遞方式類型字節(jié)數(shù)類型字節(jié)數(shù)char2unsignedlong4unsignedchar2float8short2double8int2near指針2(偏移量)unsignedint2far指針8(段:偏移量)long4第9章模塊化程序設(shè)計(jì)與混合編程
(4)被調(diào)函數(shù)的返回值通常放在AX(16位)或DX:AX(32位)內(nèi),但若是float、double、struct、union類型,則返回值放入靜態(tài)數(shù)據(jù)區(qū),然后返回其指針。(5)被調(diào)函數(shù)要保護(hù)的寄存器,同嵌入?yún)R編中對(duì)寄存器的限制情況相同。第9章模塊化程序設(shè)計(jì)與混合編程【例9.8】編寫一個(gè)能按用戶指定的內(nèi)存地址及長(zhǎng)度以十六進(jìn)制格式顯示內(nèi)存單元內(nèi)容的程序。
分析:從鍵盤接收用戶輸入的內(nèi)存地址及內(nèi)存長(zhǎng)度的工作可由C語(yǔ)言完成,因?yàn)镃語(yǔ)言的庫(kù)函數(shù)printf()及scanf()在給出輸入提示,讀取用戶輸入方面比較方便。對(duì)于讀取指定地址處的數(shù)據(jù),匯編語(yǔ)言則是最方便的,故這部分工作由一個(gè)匯編模塊完成。整個(gè)程序如下:C語(yǔ)言模塊:第9章模塊化程序設(shè)計(jì)與混合編程#include <stdio.h>
extern void move(char*,unsignedint,unsigned
int,unsigned
int);
main()
{
unsigned intsegment,offset,number;
char buf[20];
int i;
printf("\n Pleaseinputtheaddress(segment:offset):");
scanf("%x:%x",&segment,&offset);
printf("\n
Plesaeinputthenumber(lessthan20):");
scanf("%u",&number);
move(buf,number,offset,segment);
printf("\n");
for(i=0;i<number;i++)
printf(" %2x ",buf[i]);
}
(本模塊在編譯時(shí)用small模式)第9章模塊化程序設(shè)計(jì)與混合編程匯編語(yǔ)言模塊:
.MODEL SMALL
.CODE
PUBLIC _move
_move PROC
PUSH BP
MOV BP,SP
PUSH SI
PUSH DI
PUSH DS
MOV DI,[BP+4]
MOV CX,[BP+6]
LDS SI,[BP+8]
CLD
REP MOVSB
POP DS
POP DI
POP SI
POP BP
_move ENDP
END第9章模塊化程序設(shè)計(jì)與混合編程
在上程序中,C語(yǔ)言部分先提示用戶輸入要顯示內(nèi)存的段地址和偏移量值,然后讀取這二個(gè)數(shù)(以十六進(jìn)制方式讀取,因?yàn)橐话阍诒硎镜刂窌r(shí)習(xí)慣用這種進(jìn)制)賦給變量segment和offset。其次,提示用戶輸入要顯示的內(nèi)存單元的個(gè)數(shù)(為簡(jiǎn)單起見,不超過20個(gè)),然后將這一數(shù)據(jù)讀到變量number中。最后,調(diào)用匯編函數(shù)_move將用戶指定內(nèi)存的內(nèi)容傳送到位于main函數(shù)內(nèi)的局部變量buf中。_move函數(shù)四個(gè)參數(shù)的含義依次為:接收數(shù)據(jù)的目標(biāo)地址,要傳送的內(nèi)存單元個(gè)數(shù),要傳送的內(nèi)存起始位置的偏移量和段地址。在收到_move函數(shù)傳來(lái)的數(shù)據(jù)后,main()函數(shù)再調(diào)用printf()庫(kù)函數(shù)將這些數(shù)據(jù)以十六進(jìn)制顯示在屏幕上。
第9章模塊化程序設(shè)計(jì)與混合編程程序運(yùn)行結(jié)果如下(畫線部分為鍵入內(nèi)容):Pleaseinputtheaddress(segment:offset):0x0000:0x002f
Plesaeinputthenumber(lessthan20):10
fff06fffef0fff06fffef0fff0ff9a第9章模塊化程序設(shè)計(jì)與混合編程
從輸出結(jié)果可以看出,有些內(nèi)存單元的內(nèi)容顯示有誤,因?yàn)槭前醋止?jié)顯示的內(nèi)存內(nèi)容,一個(gè)數(shù)據(jù)應(yīng)不大于FFH才對(duì),而有些單元顯示的卻是四位十六進(jìn)制數(shù),錯(cuò)在哪兒呢?讓我們分析一下C語(yǔ)言模塊在編譯后生成的部分匯編代碼,其中語(yǔ)句
for(i=0 ;i<number ;i++)
printf("%2x",buf[i]) ;
對(duì)應(yīng)的代碼如下:第9章模塊化程序設(shè)計(jì)與混合編程
xor
si,si
;完成 i=0
jmp short @5
@4: mov al,byte ptr [bp+si-20]
;取出buf[i]的內(nèi)容,取一個(gè)字節(jié),這是正確的
cbw
;將AL內(nèi)容符號(hào)擴(kuò)展為一個(gè)字(這是導(dǎo)致錯(cuò)誤處)
push ax ;調(diào)用printf所需的第一個(gè)參數(shù)壓棧
mov ax,offsetDGROUP:s@+83
push ax ;調(diào)用printf所需的第二個(gè)參數(shù)壓棧
call near ptr_printf
pop cx
pop cx
;清除堆棧中的廢參數(shù)
@3: inc si
;i++
@5: cmp
si,word ptr[bp-22] ;i<number?
jb @4第9章模塊化程序設(shè)計(jì)與混合編程
顯然,原因在于因?yàn)閴簵V荒馨醋诌M(jìn)行,AL內(nèi)的待顯示內(nèi)容被CBW語(yǔ)句符號(hào)擴(kuò)展為一個(gè)字,然后通過堆棧傳遞給了printf函數(shù),而printf并不知道原參數(shù)是一個(gè)字還是一個(gè)字節(jié),它按一個(gè)字進(jìn)行了顯示,若AL內(nèi)的二進(jìn)制數(shù)最高位1,則符號(hào)擴(kuò)展后AH內(nèi)為FFH,所以大于80H的數(shù)均在前面加顯示了FFH。
在C語(yǔ)言條件下顯然無(wú)法改正上述錯(cuò)誤,我們將數(shù)據(jù)的顯示工作移到匯編代碼內(nèi)進(jìn)行,就很容易按我們的要求進(jìn)行顯示了。改正后的程序詳見實(shí)訓(xùn)二。返回本章首頁(yè)返回上一小節(jié)返回本節(jié)首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程實(shí)訓(xùn)一鍵盤錄入數(shù)據(jù)的轉(zhuǎn)換與顯示
實(shí)訓(xùn)內(nèi)容:編一程序,能從鍵盤讀入二個(gè)五位十進(jìn)制數(shù)(1位符號(hào)位+4位數(shù)值位),并將這二個(gè)十進(jìn)制數(shù)分別轉(zhuǎn)換為二進(jìn)制數(shù),然后求其和,再將和以十進(jìn)制形式進(jìn)行顯示。
分析:這個(gè)程序主要練習(xí)十進(jìn)制數(shù)與二進(jìn)制數(shù)之間的相互轉(zhuǎn)換。由于用戶輸入的數(shù)一般是用十進(jìn)制表示的,而這些數(shù)在計(jì)算機(jī)內(nèi)存儲(chǔ)、運(yùn)算時(shí)一般都用二進(jìn)制,這就涉及到了十進(jìn)制數(shù)向二進(jìn)制數(shù)的轉(zhuǎn)換問題;當(dāng)計(jì)算結(jié)果需要顯示或打印時(shí),又要將二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù),這又涉及到二進(jìn)制數(shù)如何轉(zhuǎn)換為十進(jìn)制數(shù)。由于在計(jì)算機(jī)內(nèi)這種轉(zhuǎn)換經(jīng)常進(jìn)行,所以二進(jìn)制數(shù)與十進(jìn)制數(shù)之間的轉(zhuǎn)換算法是匯編語(yǔ)言程序員應(yīng)掌握的基本算法之一。第9章模塊化程序設(shè)計(jì)與混合編程
由于程序較大,我們將其分在二個(gè)模塊內(nèi),模塊A負(fù)責(zé)十制數(shù)的讀取、二個(gè)數(shù)的求和,以及和的顯示工作,模塊B負(fù)責(zé)將十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制,以及將二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)。由于二個(gè)模塊內(nèi)數(shù)據(jù)傳遞關(guān)系比較復(fù)雜,所以采用COMMON段可避免在模塊間傳遞參數(shù),使源程序結(jié)構(gòu)清析。另外,為突出主要算法,減少不必要的細(xì)節(jié)考慮,將用戶輸入的數(shù)據(jù)限制在4位(不含符號(hào)位)以內(nèi),這樣數(shù)值在-9999至+9999范圍以內(nèi),轉(zhuǎn)換為二進(jìn)制后在16位補(bǔ)碼的表示范圍內(nèi),而其相加后的和也在16位補(bǔ)碼的表示范圍內(nèi);同時(shí),在將二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)顯示時(shí),也只須考慮萬(wàn)位及以下數(shù)字的轉(zhuǎn)換即可,不存在十萬(wàn)位以上的數(shù)字。
參考程序:第9章模塊化程序設(shè)計(jì)與混合編程模塊A:
EXTRN ASC_TO_BIN:FAR,BIN_TO_ASCII:FAR
DATA SEGMENT COMMON
INPUT_MESSAGEDB 0AH,
DB‘PLEASEINPUTANUMBER(LESSTHAN5FIGURES):$’
IN_ASC_BUF DB 6 ;十進(jìn)制數(shù)的輸入緩沖區(qū),共可接收6個(gè)字符
DB ? ;保留,用于10號(hào)調(diào)用時(shí)DOS填入實(shí)際輸入字符個(gè)數(shù)
DB 6DUP(?);一個(gè)符號(hào)位,四位數(shù)字ASCII碼,加上一個(gè)回車
;符,共計(jì)6字符
BIN_BUF1 DW ?;將第一個(gè)數(shù)轉(zhuǎn)換為二進(jìn)制后,放于此處
OUTPUT_MESSAGE DB 0AH,‘THESUM IS:’,‘$’
OUT_ASC_SUM DB 6DUP(?),‘$'
;將二個(gè)數(shù)的和轉(zhuǎn)換為ASCII碼后,放于此處,以供9號(hào)調(diào)用顯示
DATA ENDS第9章模塊化程序設(shè)計(jì)與混合編程CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV DX,OFFSET INPUT_MESSAGE
MOV AH,9
INT 21H ;提示輸入一個(gè)數(shù)
MOV DX,OFFSET IN_ASC_BUF
MOV AH,10
INT 21H ;讀取第一個(gè)數(shù)
CALL ASC_TO_BIN ;轉(zhuǎn)換第一個(gè)數(shù)為二進(jìn)制
MOV BIN_BUF1,AX ;保存第一個(gè)數(shù)
MOV DX,OFFSET INPUT_MESSAGE
MOV AH,9
INT 21H ;提示輸入一個(gè)數(shù)第9章模塊化程序設(shè)計(jì)與混合編程 MOV DX,OFFSET IN_ASC_BUF
MOV AH,10
INT 21H ;讀取第二個(gè)數(shù)
CALL ASC_TO_BIN ;轉(zhuǎn)換第二個(gè)數(shù)為二進(jìn)制
ADD AX,BIN_BUF1 ;計(jì)算這二個(gè)數(shù)之和
CALL BIN_TO_ASCII
;將和轉(zhuǎn)換為ASCII碼,以供顯示用
MOV DX,OFFSET OUTPUT_MESSAGE
MOV AH,9
INT 21H
MOV DX,OFFSET OUT_ASC_SUM
MOV AH,9
INT 21H
MOV AH,4CH
INT 21H
CODE ENDS
END START第9章模塊化程序設(shè)計(jì)與混合編程模塊B:
PUBLIC ASC_TO_BIN,BIN_TO_ASCII
DATA SEGMENT COMMON
INPUT_MESSAGE DB0AH,
DB‘PLEASEINPUTANUMBER(LESSTHAN5FIGURES):$’
IN_ASC_BUF DB6 ;十進(jìn)制數(shù)的輸入緩沖區(qū),共可接收6個(gè)字符
DB? ;保留,用于10號(hào)調(diào)用時(shí)DOS填入實(shí)際輸入字符個(gè)數(shù)
DB6DUP(?)
;一個(gè)符號(hào)位,四位數(shù)字ASCII碼,加上一個(gè)回車符,共計(jì)6字符
BIN_BUF1 DW? ;將第一個(gè)數(shù)轉(zhuǎn)換為二進(jìn)制后,放于此處
OUTPUT_MESSAGE DB0AH,'THESUMIS:','$'
OUT_ASC_SUM DB 6DUP(?),'$'
;將二個(gè)數(shù)的和轉(zhuǎn)換為ASCII碼后,放于此處,以供9號(hào)調(diào)用顯示
DATA ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:DATA
ASC_TO_BIN PROC FAR第9章模塊化程序設(shè)計(jì)與混合編程;ASCII碼轉(zhuǎn)換為二進(jìn)制數(shù)
;入口:十進(jìn)制數(shù)的ASCII碼在IN_ASC_BUF內(nèi)
;出口:轉(zhuǎn)換后的二進(jìn)制數(shù)在AX內(nèi)
;算法:先將其轉(zhuǎn)換成十進(jìn)制數(shù)字,再用累加和乘10加X
;的方法變成二進(jìn)制數(shù),如將
;358轉(zhuǎn)換為二進(jìn)制數(shù),可先將累加和賦0,再計(jì)算
;(((0*10+3)*10+5)*10+8),結(jié)果為二
;進(jìn)制數(shù),再由符號(hào)位決定是否需要求補(bǔ)。
MOV CL,IN_ASC_BUF+1 ;取字符個(gè)數(shù)
MOV CH,0
DEC CL ;扣除符號(hào)位
MOV BX,OFFSET IN_ASC_BUF+3
;調(diào)整BX指向十進(jìn)制數(shù)的最高位
PUSH BX
PUSH CX第9章模塊化程序設(shè)計(jì)與混合編程L1:
MOV AL,[BX]
AND AL,0FH
MOV [BX],AL
INC BX
LOOP L1 ;將所有數(shù)字字符的高四位清0,使之變?yōu)閿?shù)字值
POP CX
POP BX
MOV AX,0 ;累加和賦初值
MOV SI,10第9章模塊化程序設(shè)計(jì)與混合編程L2:
MUL SI
ADD AL,[BX]
ADC AH,0
INC BX
LOOP L2 ;累加乘10
CMP IN_ASC_BUF+2,'+'
JZ L3 ;符號(hào)是正號(hào),轉(zhuǎn)移
NEG AX ;符號(hào)是負(fù)號(hào),求補(bǔ)
L3:
RET
ASC_TO_BIN ENDP第9章模塊化程序設(shè)計(jì)與混合編程BIN_TO_ASCII PROC FAR
;將二進(jìn)制數(shù)轉(zhuǎn)換為對(duì)應(yīng)十進(jìn)制數(shù)數(shù)字的ASCII碼
;入口:二進(jìn)制數(shù)在AX內(nèi)
;出口:轉(zhuǎn)換后的ASCII碼在OUT_ASC_SUM變量?jī)?nèi)
;算法:AX中的數(shù)范圍在+32767到-32768之間,先檢查AX中
;的符號(hào)位,以決定輸出“+”
;還是“-”,若是負(fù)數(shù),應(yīng)先求補(bǔ),得到原碼后即可與正數(shù)作
;統(tǒng)一處理。轉(zhuǎn)換方法為將被轉(zhuǎn)換
;的二進(jìn)制數(shù)先除以10000,商;即為萬(wàn)位數(shù),再將余數(shù)除以
;1000,商為千位數(shù),以此類推,
;求出百、十位數(shù),剩下的為個(gè)位數(shù)。最后,將各個(gè)數(shù)加上
;30H,即成為對(duì)應(yīng)字符。
MOV OUT_ASC_SUM,'+'
CMP AX,0
JGE L4 ;不是負(fù)數(shù),轉(zhuǎn)移
NEG AX
MOV OUT_ASC_SUM,'-'第9章模塊化程序設(shè)計(jì)與混合編程L4:
CWD
MOV BX,10000
DIV BX
ADD AL,30H;將萬(wàn)位轉(zhuǎn)換為數(shù)字(商應(yīng)在AX內(nèi),但因?yàn)樯滩淮笥?/p>
;3,所以有效部分在AL內(nèi))
MOV OUT_ASC_SUM+1,AL;保存萬(wàn)位數(shù)字
MOV AX,DX ;將余數(shù)置入AX內(nèi),以便當(dāng)作被除數(shù)
CWD
MOV BX,1000
DIV BX
ADD AL,30H
MOV OUT_ASC_SUM+2,AL;保存千位數(shù)字
MOV AX,DX ;將余數(shù)置入AX內(nèi),以便當(dāng)作被除數(shù)
MOV BL,100
DIV BL
ADD AL,30H第9章模塊化程序設(shè)計(jì)與混合編程 MOV OUT_ASC_SUM+3,AL ;保存百位數(shù)字
MOV AL,AH
CBW
MOV BL,10
DIV BL
ADD AL,30H
MOV OUT_ASC_SUM+4,AL ;保存十位數(shù)字
ADD AH,30H
MOV OUT_ASC_SUM+5,AH ;保存?zhèn)€位數(shù)字
RET
BIN_TO_ASCII ENDP
CSEG ENDS
END第9章模塊化程序設(shè)計(jì)與混合編程程序運(yùn)行結(jié)果如下(畫線部分為鍵入內(nèi)容):D:\MASM>A
PLEASEINPUTANUMBER(LESSTHAN5FIGUERS):-2000
PLEASEINPUTANUMBER(LESSTHAN5FIGUERS):+3310
THESUMIS:+01310返回本章首頁(yè)第9章模塊化程序設(shè)計(jì)與混合編程實(shí)訓(xùn)二C語(yǔ)言調(diào)用匯編語(yǔ)言子程序進(jìn)行數(shù)據(jù)傳遞與顯示
實(shí)訓(xùn)內(nèi)容:同本章例9.8,但要克服例9.8中的顯示缺陷
分析:因?yàn)樵趐rintf()中控制一個(gè)字節(jié)數(shù)據(jù)的顯示格式比較困難,故我們將顯示部分也在匯編模塊中完成即可。
參考程序:
匯編程序:
.MODEL SMALL
.CODE
PUBLIC _disp
;聲明全局符號(hào),以便C模塊調(diào)用CHAR_DISPLAYPROC
;將AL內(nèi)“0000 XXXX”格式的數(shù)據(jù)以十六進(jìn)制形式顯示出來(lái)(一個(gè)字符)
;入口參數(shù):在AL內(nèi)(AL的高四位必須為0,低四位為待顯示數(shù)據(jù))
;出口參數(shù):將對(duì)應(yīng)十六進(jìn)制字符顯示在屏幕上第9章模塊化程序設(shè)計(jì)與混合編程 CMP AL,9
JA @@1
;若AL>9,則需要顯示A~F之間的一個(gè)字母,轉(zhuǎn)到@@1處處理
MOV AH,2
MOV DL,AL
ADD DL,30H
INT 21H
RET
@@1:
SUB AL,0AH
MOV DL,'A'
ADD DL,AL
MOV AH,2
INT 21H
RET
CHAR_DISPLAY ENDP第9章模塊化程序設(shè)計(jì)與混合編程HEX_DISP PROC
;將AL內(nèi)的數(shù)以十六進(jìn)制格式顯示在屏幕上
;入口參數(shù):在AL內(nèi)
;出口參數(shù):對(duì)應(yīng)數(shù)據(jù)顯示在屏幕上(二個(gè)字符)
PUSH DX
PUSH CX
PUSH AX
MOV CL,4
SHR AL,CL
;將AL右移四位,使得高四位為0,原高四位數(shù)據(jù)到低四位上
CALL CHAR_DISPLAY;將AL內(nèi)原高四位上的數(shù)據(jù)顯示出來(lái)
POP AX ;恢復(fù)原AL內(nèi)的數(shù)據(jù)
AND AL,0FH ;AL高四位清0,以使顯示低四位上的數(shù)據(jù)
CALL CHAR_DISPLAY ;顯示AL低四位上的數(shù)據(jù)
POP CX
POP DX
RET
HEX_DISP ENDP第9章模塊化程序設(shè)計(jì)與混合編程SPACE_DISP PROC
;顯示二個(gè)空格,以便將屏幕上的十六進(jìn)制數(shù)隔開,無(wú)入口參數(shù)
PUSH DX
PUSH AX
MOV DL,''
MOV AH,2
INT 21H
MOV DL,''
MOV AH,2
INT 21H
POP AX
POP DX
RET
SPACE_DISP EN
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 【正版授權(quán)】 IEC TS 63165:2024 EN Requirements for industrial water quality analyzer system – Photometry
- 2025年浙江省安全員-C證考試(專職安全員)題庫(kù)及答案
- 2025-2030年中國(guó)鋼材加工配送中心行業(yè)運(yùn)行態(tài)勢(shì)及發(fā)展規(guī)劃分析報(bào)告
- 2025-2030年中國(guó)金融信息化行業(yè)運(yùn)營(yíng)狀況及發(fā)展前景分析報(bào)告
- 2025-2030年中國(guó)酒石酸美托洛爾緩釋片行業(yè)運(yùn)行動(dòng)態(tài)與十三五規(guī)劃研究報(bào)告
- 2025-2030年中國(guó)螺旋泵市場(chǎng)運(yùn)營(yíng)狀況及發(fā)展前景分析報(bào)告
- 2025-2030年中國(guó)薯?xiàng)l行業(yè)運(yùn)行狀況與前景趨勢(shì)分析報(bào)告
- 西雙版納職業(yè)技術(shù)學(xué)院《集裝箱與國(guó)際物流運(yùn)輸管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 河北師范大學(xué)《節(jié)目策劃》2023-2024學(xué)年第二學(xué)期期末試卷
- 西京學(xué)院《商務(wù)應(yīng)用文寫作》2023-2024學(xué)年第二學(xué)期期末試卷
- 現(xiàn)代康復(fù)治療腕管綜合癥
- 福建公安基礎(chǔ)知識(shí)真題匯編2
- 2024年金融理財(cái)-特許金融分析CFA考試近5年真題附答案
- 2024橋式門式起重機(jī)大修項(xiàng)目及其技術(shù)標(biāo)準(zhǔn)
- 部編版七年級(jí)歷史下冊(cè)全冊(cè)導(dǎo)學(xué)案
- 2024風(fēng)力發(fā)電葉片維保作業(yè)技術(shù)規(guī)范
- 公路工程監(jiān)理工作指導(dǎo)手冊(cè)
- 第2課?玩泥巴(課件)科學(xué)一年級(jí)下冊(cè)
- 學(xué)校臨聘人員規(guī)范管理自查報(bào)告
- 小學(xué)數(shù)學(xué)課堂有效教學(xué)現(xiàn)狀調(diào)查問卷分析報(bào)告
- 食材配送服務(wù)方案投標(biāo)方案(技術(shù)方案)
評(píng)論
0/150
提交評(píng)論