《匯編語(yǔ)言程序設(shè)計(jì)(第2版)》第九章 模塊化程序設(shè)計(jì)與混合編程_第1頁(yè)
《匯編語(yǔ)言程序設(shè)計(jì)(第2版)》第九章 模塊化程序設(shè)計(jì)與混合編程_第2頁(yè)
《匯編語(yǔ)言程序設(shè)計(jì)(第2版)》第九章 模塊化程序設(shè)計(jì)與混合編程_第3頁(yè)
《匯編語(yǔ)言程序設(shè)計(jì)(第2版)》第九章 模塊化程序設(shè)計(jì)與混合編程_第4頁(yè)
《匯編語(yǔ)言程序設(shè)計(jì)(第2版)》第九章 模塊化程序設(shè)計(jì)與混合編程_第5頁(yè)
已閱讀5頁(yè),還剩75頁(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)介

匯編語(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論