微型計算機原理與接口技術(shù):第三章 匯編語言程序設計_第1頁
微型計算機原理與接口技術(shù):第三章 匯編語言程序設計_第2頁
微型計算機原理與接口技術(shù):第三章 匯編語言程序設計_第3頁
微型計算機原理與接口技術(shù):第三章 匯編語言程序設計_第4頁
微型計算機原理與接口技術(shù):第三章 匯編語言程序設計_第5頁
已閱讀5頁,還剩78頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第三章匯編語言程序設計本章學習要點:通過本章學習應掌握匯編語言的編程方法和程序結(jié)構(gòu),培養(yǎng)模塊化程序設計思想。逐步熟練掌握指令、偽指令在程序設計中的使用方法和程序的調(diào)試方法。本章主要學習內(nèi)容有:

1、掌握匯編語言程序結(jié)構(gòu)(分支、循環(huán)和子程序)

2、子程序參數(shù)的傳遞方法

3、DOS功能調(diào)用

5.1基本知識一、流程圖繪制方法流程圖是程序設計的基礎,它是程序算法的圖形描述,以圖形的方式把解決問題的先后次序及程序的邏輯結(jié)構(gòu)直觀地、形象地描述出來。使解題思路表達清晰,便于理解和編制程序。為一個復雜任務繪制流程圖時,首先要將任務分解,化為一個個小的任務模塊,然后再對每個小模塊再進行分解,直至每個小模塊表述的都很清晰為止。故流程圖的繪制也可以分為幾級來畫,從概括到具體,由粗到細,逐步求精。流程圖一般由執(zhí)行框、判別框、起止框和流向線四部分組成,如圖所示。

執(zhí)行框:用于說明某一段程序或某一模塊的功能。通常有一個入口和一個出口。判別框:表示程序分支的流向判斷,框內(nèi)寫判別條件。這種框通常有一個入口,多個出口,每個出口要注明分支流向條件。起止框:表示一個程序或一個程序模塊的開始和結(jié)束。起始框內(nèi)通常標注程序名、標號或“開始”,它僅有一個出口。終止框內(nèi)通常標注“結(jié)束”、“返回”等,它僅有一個入口。起止框:表示一個程序或一個程序模塊的開始和結(jié)束。起始框內(nèi)通常標注程序名、標號或“開始”,它僅有一個出口。終止框內(nèi)通常標注“結(jié)束”、“返回”等,它僅有一個入口。

例:在內(nèi)存BUF字節(jié)數(shù)據(jù)緩沖區(qū)中存放著若干無符號數(shù),編寫一個程序,從數(shù)據(jù)區(qū)中找出最大值,并保存到AL寄存器中。分析:若是人工查找最大值,則要從第一個數(shù)據(jù)開始向后查看,將看到的第一個數(shù)據(jù)作為初始最大值,再同下一個數(shù)據(jù)進行比較,將比較后得到的最大值記住,然后再用這個最大值同下一個數(shù)據(jù)進行比較,如此下去直至全部數(shù)據(jù)比較完畢為止,那么最大值也就在大腦中產(chǎn)生了。從上面的分析,可以找出用計算機解決這一問題的算法。將寄存器BX作為數(shù)據(jù)指針,讓它指向數(shù)據(jù)緩沖區(qū),并把第一個數(shù)據(jù)作為初始最大值從內(nèi)存中取出送AL寄存器保存。調(diào)整BX,使其再指向第二個數(shù)據(jù),將該數(shù)據(jù)同初始最大值進行比較,如果這個數(shù)據(jù)比初始最大值大,就把該數(shù)據(jù)作為新的最大值保存到AL寄存器中,否則放棄該數(shù)據(jù),再繼續(xù)與下一個數(shù)據(jù)進行比較,這樣直至比較完全部數(shù)據(jù)后,在AL寄存器中中保存的就是數(shù)據(jù)的最大值。程序框圖如下:

1 DATA SEGMENT ;定義數(shù)據(jù)段

2 BUF DB85,90,78,97,…

;數(shù)據(jù)區(qū)

3 COUNT EQU$-BUF ;計算數(shù)據(jù)個數(shù)

4 DATA ENDS5 STACK SEGMENTPARASTACK ;定義堆棧段

6 DW100DUP(?) ;定義100個字的堆??臻g

7 STACK ENDS8 CODE SEGMENT ;定義代碼段

9 MAIN PROCFAR ;主程序開始

10 ASSUME CS:CODE,DS:DATA,SS:STACK;分配段寄存器

11 PUSH DS ;保護返回地址

12 MOV AX,013 PUSH AX14 MOV AX,DATA ;裝填數(shù)據(jù)段寄存器

15 MOV DS,AX

16 LEA BX,BUF ;數(shù)據(jù)指針BX指向數(shù)據(jù)區(qū)首地址

17 MOV AL,[BX] ;取初始值作初始最高分

18MOV CX,COUNT-1 ;設置計數(shù)器初值

19LP:INCBX ;修改數(shù)據(jù)指針,BX指向下一數(shù)據(jù)

20 CMP AL,[BX] ;數(shù)據(jù)區(qū)中的分數(shù)同“最大值”比較

21 JAE NEXT ;最大值比下一個數(shù)據(jù)大或相等時轉(zhuǎn)移

22 MOV AL,[BX] ;新的“最大值”送AL保存

23NEXT:LOOP LP ;計數(shù)器(CX)>0時,轉(zhuǎn)移到LP

24RET ;返回DOS25MAINENDP ;過程結(jié)束

26CODEENDS ;代碼段結(jié)束

27 END MAIN

;源程序結(jié)束

程序中第11~13語句的作用是保證用戶程序結(jié)束后能夠正確返回DOS。用戶的可執(zhí)行程序(

EXE)裝入內(nèi)存后,用戶程序的目標代碼一定是直接加載在程序段前綴(ProgramSegmentPrefix,簡稱PSP)的后面。PSP的長度為100H字節(jié),它給出了用戶可執(zhí)行文件的若干控制信息,在PSP的開始處(第1、2字節(jié))有一條中斷指令“INT20H”的代碼。這條指令具有結(jié)束用戶程序,返回操作系統(tǒng)的功能。通過該指令返回DOS是用戶程序常用的一種方法。用戶程序結(jié)束后如何返回這里呢?首先把用戶程序設置成一個過程,其類型為FAR。由于可執(zhí)行文件裝入內(nèi)存后,DS和ES兩個段寄存器都指向PSP,所以用第11語句“PUSHDS”指令把DS內(nèi)容壓入堆棧,接著用第12、13語句把偏移量00H壓入堆棧。這樣執(zhí)行第24語句RET返回指令后,DOS就會把原先壓入堆棧的DS值和偏移量00H彈出,分別送入CS和IP,使程序轉(zhuǎn)到PSP開始處去執(zhí)行“INT20H”指令。

結(jié)束用戶程序也可以使用中斷指令“INT21H”返回操作系統(tǒng)。此時,用戶程序不再設置為過程,只要在程序結(jié)束時用以下兩條指令即可。

MOV AH,4CH INT 21H程序的代碼段可以改寫為:

CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACK

START:MOVAX,DATA

MOVDS,AX┇

;省略部分同前一程序

NEXT:LOOPLP MOVAH,4CH ;功能號4CH送AH INT 21H ;調(diào)用DOS的21H號中斷

CODEENDS ENDSTART

在程序設計時,易采用“自上而下、逐步求精”的實施方法,此方法又稱為系統(tǒng)化程序設計方法。首先把一個大型程序分解成幾個主要的模塊。最高層次部分說明這些模塊之間的關(guān)系以及它們的功能,也就是說,最高層次部分是對整個程序的概述。而每個主要的模塊再分解成幾個較小的模塊,然后繼續(xù)分解成更小的模塊,直到每個模塊內(nèi)的操作步驟都很清楚、容易理解為止??梢杂勺钚〉哪K開始編寫程序,經(jīng)測試通過后再一直往上做,直到最終完成。5.2程序設計的基本方法

5.2.1順序程序設計順序結(jié)構(gòu)是最簡單的一種程序結(jié)構(gòu)形式。從開始到結(jié)束,完全按照語句順序逐條執(zhí)行的指令序列,它沒有分支、循環(huán)和轉(zhuǎn)移。從程序流程圖看,順序結(jié)構(gòu)的程序只有一個起始框、終止框和若干個執(zhí)行框,沒有判別框。采用順序結(jié)構(gòu)的程序一般都是簡單程序。由于程序設計比較簡單,一般可不必畫出流程圖,直接寫出源程序,下面舉例加以說明。

【例3-1】求兩個無符號數(shù)的平均值。這兩個數(shù)分別放在X單元和Y單元中,而平均值放在Z單元中,在此設X=6、Y=8。源程序編制如下:

DATA SEGMENT XDB 6 YDB8 ZDB? DATA ENDS STACKSEGMENTPARASTACK DW 100DUP(?) STACKENDS CODE SEGMENT MAINPROCFAR ASSUMECS:CODE,DS:DATA,SS:STACK

PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV AL,X ;AL

X ADD AL,Y ;AL

(X+Y)

MOVAH,0 ;AL擴展為字

MOV BL,2 ;BL

除數(shù)2 DIV BL ;(AX)÷2,AL

商,AH

余數(shù)

MOV Z,AL ;Z

RETMAIN ENDPCODE ENDS END MAIN

【例3-2】在內(nèi)存中自TAB開始的16個單元連續(xù)存放著0至15的平方值(稱為平方表)。任給一個數(shù)x(0

x

15),求x的平方值,并把結(jié)果放入y單元中。(P143,注:本程序優(yōu)于課本)分析一下表的存放規(guī)律可知,表地址與數(shù)x的和正是x2值所在存儲單元的地址。設X=12,程序如下:

DATASEGMENTTABDB0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225X EQU 12D

;書上是“?”

YDB ?DATAENDSSTACKSEGMENTPARASTACKDW100DUP(?)STACKENDSCODESEGMENTASSUME CS:CODE,DS:DATA,SS:STACK

START: MOV AX,DATA MOV DS,AX MOV BX,X MOV AL,TAB[BX] ;把表中的X2值送AL MOV Y,AL ;X2值送Y單元

MOV AH,4CH INT 21H CODE ENDS END START

5.2.2分支程序設計許多實際問題都需要根據(jù)不同的情況進行不同的處理。反映到計算機程序中就是根據(jù)不同的條件,跳到不同的程序段去執(zhí)行相應的程序,這樣的程序就稱為分支程序。也正因為如此,計算機才有了分析和判斷的能力。在匯編語言程序設計中,可以用條件轉(zhuǎn)移指令實現(xiàn)分支結(jié)構(gòu)。

1.利用比較轉(zhuǎn)移指令實現(xiàn)分支兩路分支只要用條件轉(zhuǎn)移指令就能實現(xiàn),對多路分支則要采用多次判斷轉(zhuǎn)移的方法實現(xiàn),每次判斷轉(zhuǎn)移形成兩路分支,n次判斷轉(zhuǎn)移可以形成n+1路分支。(P145)

1 x>0

【例3-3】求解符號函數(shù)Y=

0 x=0(-128

x

127)

-1 x<0

這是一個簡單的分支結(jié)構(gòu),任意給定x值,在此設x=-2,存放在x單元,函數(shù)值y存放在y單元,根據(jù)x的值確定y的值。程序流程圖如圖所示。

編寫程序如下:(書上例題有錯) DATASEGMENTX DB ?2

;書上是“X” Y DB ? DATAENDS STACK SEGMENTPARASTACK DW100DUP(?) STACK ENDS CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACK MAINPROCFAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX

MOV AL,X ;AL

X CMP AL,0 JGE BIG ;X0時跳轉(zhuǎn)

MOV AL,-1 ;X<0時,Y-1 JMPS1 BIG: JEEQZ ;X=0時跳轉(zhuǎn)

MOVAL,1 ;X>0時,Y1 JMPS1 EQZ: MOVAL,0 ;X=0時,Y0 S1: MOVY,AL RETMAIN ENDPCODE ENDS ENDMAIN課后請將本例與書上例題比較,掌握這兩種程序結(jié)構(gòu)的使用方法。

┇ CMP AL,00H JZSBR0 CMP AL,01H JZSBR1 ┇ CMP AL,07H JZ SBR7 ┇5.2.3循環(huán)程序設計

循環(huán)結(jié)構(gòu)是重復執(zhí)行某一段程序的一種結(jié)構(gòu)形式。凡是需重復執(zhí)行的程序段都可以按循環(huán)結(jié)構(gòu)設計。

一、單循環(huán)程序設計

1、循環(huán)程序的兩種結(jié)構(gòu)形式

【例3-5】在內(nèi)存BUF單元中存放著若干字節(jié)型帶符號數(shù),編寫程序統(tǒng)計其中負數(shù)的個數(shù),統(tǒng)計結(jié)果放在REST單元。(P150,例1)

DATA SEGMENT BUFDB-1,23,-4,67,…

CONTEQU$-BUF RESTDW? DATA ENDS CODESEGMENT MAIN PROCFAR ASSUMECS:CODE,DS:DATA PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX

MOVBX,OFFSETBUF MOVCX,CONT ;數(shù)據(jù)個數(shù)送CX MOVDX,0 ;DXLP1:MOVAL,[BX] ;取數(shù)據(jù)送AL ANDAL,AL ;影響標志位

JNSPP ;正數(shù)不統(tǒng)計,跳轉(zhuǎn)

INCDX ;是負數(shù)DX加1PP: INCBX ;修改數(shù)據(jù)指針

LOOPLP1 ;判斷下一數(shù)據(jù)正負

MOVREST,DX ;存結(jié)果

RETMAIN ENDPCODE ENDSENDMAIN

【例3-5】在內(nèi)存Y單元中存放著數(shù)n,編寫程序把數(shù)n中“1”的個數(shù)統(tǒng)計出來放在COUNT單元。(P150,例2)一種方法是對數(shù)n逐步按位測試來統(tǒng)計“1”的個數(shù),以數(shù)n的位長作為循環(huán)結(jié)束條件。這種方法對n=0的情況也要從頭至尾逐位判斷,能否把n=0的情況立刻判斷出來縮短程序執(zhí)行時間呢?這就要采用“先判斷后執(zhí)行”循環(huán)結(jié)構(gòu),首先測試n是否為0來作為循環(huán)結(jié)束條件,節(jié)省程序執(zhí)行時間。這是一種按條件控制循環(huán)結(jié)束的方法。程序框圖及源程序如下:

DATA SEGMENT YDW n ;調(diào)試程序時“n”應寫成具體數(shù)值

COUNTDW ? DATA ENDS CODESEGMENT MAIN PROCFAR ASSUMECS:CODE,DS:DATA PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV CX,0 ;初始化CX,用于計數(shù)

MOV AX,Y ;數(shù)n送AX

RP: ANDAX,AX;測試AX內(nèi)容,也可用TESTAX,0FFFFH JZEXI ;(AX)=0轉(zhuǎn)移

SHIF: SHLAX,1 ;AX內(nèi)容邏輯左移一位

JNCZR ;CF中是0轉(zhuǎn)移

INCCX ;CF中是1,CX內(nèi)容加1ZR: JMPRP ;返回繼續(xù)檢測

EXI: MOVCOUNT,CX ;把n中1的個數(shù)送COUNT單元

RETMAIN ENDPCODE ENDSENDMAIN

【例3-6】設計一個程序使它能夠把BX寄存器內(nèi)的二進制數(shù)用十六進制數(shù)的形式在屏幕上顯示出來。根據(jù)題意應該把BX中的二進制數(shù)每四位劃分為一組,從左到右依次把每組的十六進制值在屏幕上顯示出來,顯然這個問題可以使用循環(huán)結(jié)構(gòu)完成,每次循環(huán)顯示一位十六進制數(shù),由于BX字長16位,每次處理4位,共需循環(huán)處理4次,這樣循環(huán)次數(shù)是已知的,可以使用循環(huán)計數(shù)的方法控制循環(huán)。在循環(huán)體內(nèi)先將二進制數(shù)分組,然后再將其轉(zhuǎn)換為可顯示的ASCII碼,通過DOS系統(tǒng)功能調(diào)用將字符從顯示器上顯示出來(關(guān)于DOS系統(tǒng)功能調(diào)用將在以后講述)。字符0~9的ASCII碼為30H~39H,而字母A~F的ASCII碼為41H~46H,所以將4位二進制數(shù)轉(zhuǎn)換為ASCII碼的方法是,值為0~9的4位二進制數(shù)只要加上30H后即為ASCII碼,而對于值為10~15的4位二進制數(shù)還要再加上7才能顯示出字符A~F,因為從3AH~40H一共有7個字符需要跳過去。程序框圖及程序如下:

CODE SEGMENTMAIN PROCFARASSUMECS:CODE PUSH DS MOV AX,0 PUSH AX MOV BX,10101011111101B ;二進制數(shù)送BX MOV CH,4 ;共需轉(zhuǎn)換4組ROT: MOV CL,4 ;每組四位

ROL BX,CL ;左循環(huán)移位

MOV AL,BL ;AL

BL AND AL,0FH

;清AL中高4位

CMPAL,9 JBEDSP ADD AL,7 ;為轉(zhuǎn)換成A~F做準備

DISP: ADDAL,30H ;轉(zhuǎn)換成ASCII碼

MOV DL,AL ;ASCII碼送DL MOV AH,2 ;功能號送AH INT 21H ;顯示字符

DEC CH ;每完成一組轉(zhuǎn)換,CH值減1 JNZ ROT ;4組二進制數(shù)沒有轉(zhuǎn)換完轉(zhuǎn)移

MOV DL,‘H’ ;顯示字符“H”表明是十六進制

MOV AH,2 INT 21H RETMAIN ENDPCODEENDS ENDMAIN

二、多重循環(huán)程序設計多重循環(huán)又稱循環(huán)嵌套,即循環(huán)套循環(huán)。多重循環(huán)程序設計的基本方法和單重循環(huán)程序設計是一致的。在使用多重循環(huán)時,內(nèi)循環(huán)必須完整的包含在外循環(huán)之中,循環(huán)可以嵌套、并列,但不能交叉。可以從內(nèi)循環(huán)中直接跳到外循環(huán),但不能從外循環(huán)中直接跳進內(nèi)循環(huán)。無論是外循環(huán),還是內(nèi)循環(huán),決不能使循環(huán)返回到初始化部分,否則會出現(xiàn)“死循環(huán)”,這一點要特別注意。

【例3-7】從鍵盤讀入一位3~9之間的數(shù)字,輸出一個用“

”組成的三角形,例如讀入3,輸出

本題可以用雙重循環(huán)進行設計,內(nèi)層循環(huán)用CX計數(shù),控制一行輸出“

”的個數(shù),外層循環(huán)也用CX計數(shù),用來控制行數(shù)。在內(nèi)層循環(huán)開始時,首先把外層循環(huán)的CX壓入堆棧,當內(nèi)層循環(huán)結(jié)束后再立即恢復外層循環(huán)CX的計數(shù)值。(關(guān)于DOS功能調(diào)用在后面章節(jié)講解)

DATA SEGMENTMESS DB‘Pleaseinputanumber:$’DATA ENDSCODE SEGMENTASSUMEDS:DATA,CS:CODEBEGIN:MOV AX,DATA MOVDS,AX LEA DX,MESS MOVAH,09H ;DOS功能調(diào)用,顯示字符串

INT21HKEYIN:MOVAH,1 INT21H ;從鍵盤取數(shù)

CMP AL,33H ;同“3”比較

JBKEYIN ;小于“3”重新輸入

CMPAL,39H ;同“9”比較

JAKEYIN ;大于“9”重新輸入

AND AL,0FH ;把ASCII碼轉(zhuǎn)換為二進制數(shù)

CBW ;把AL中字節(jié)數(shù)據(jù)擴展成字

MOV CX,AX ;該數(shù)作為外層循環(huán)數(shù)送CX MOV AH,2 ;DOS中斷的2號功能調(diào)用

MOV DL,0DH ;0DH是“回車”的ASCII碼

INT 21H ;使光標回到所在行的行首

MOV DL,0AH ;0AH是“換行”的ASCII碼

INT 21H ;使光標換行

L2:PUSH CX ;外層循環(huán)計數(shù)值入棧保存

L1:MOV DL,‘

’ MOV AH,2 INT 21H ;在一行上循環(huán)打印“

LOOP L1

MOV DL,0DH INT 21H ;光標回到行首

MOV DL,0AH INT 21H ;光標下移一行

POP CX ;外層循環(huán)計數(shù)值出棧

LOOP L2 ;在新行上循環(huán)打印“

MOV AH,4CH INT 21HCODE ENDS END BEGIN

練習1:在字節(jié)型數(shù)據(jù)區(qū)da1中有若干個字符,編寫一個程序統(tǒng)計大寫字母B出現(xiàn)的次數(shù),結(jié)果送sum。(思考:查找替換問題)

datasegmentda1db‘eFDhi

abcd

ABCD'numequ$-da1sumdb0dataendscodesegmentmainprocfarassumecs:code,ds:datapushds

movax,0pushax

mov

ax,data

mov

ds,ax

mov

cx,numleasi,da1nt:cmpbyteptr[si],‘B'

jne

aaincsumaa:incsiloopntretmainendpcodeendsendmain

datasegment

bufdb‘eFDhi

abcd

ABCD'numequ$-bufdataendscodesegmentmainprocfarassumecs:code,ds:datapushds

movax,0pushax

mov

ax,data

mov

ds,ax

mov

cx,numleasi,buf

nt:cmp

byteptr[si],'A'

jb

aa

cmp

byteptr

[si],'Z'

ja

aa

mov

bl,[si]addbl,20h

mov[si],blaa:incsiloopntretmainendpcodeendsendmain練習2:在字節(jié)型數(shù)據(jù)區(qū)buf

中有若干個字符,編寫一個程序?qū)⑵渲械拇髮懽帜皋D(zhuǎn)換為小寫字母。(思考:小寫轉(zhuǎn)大寫)

練習3:在字節(jié)型數(shù)據(jù)區(qū)buf

中存放著若干個有符號數(shù),編寫一個程序?qū)⑵渲械淖畲髷?shù)和最小數(shù)分別存放到n_max和n_min字節(jié)單元。

datasegment

bufdb-2,5,8,-9,16h,-0ahnumequ$-da1

n_maxdb?

n_mindb?dataendscodesegmentmainprocfarassumecs:code,ds:datapushds

movax,0pushax

mov

ax,data

mov

ds,ax

leasi,buf

mov

al,[si]

mov

n_max,al

mov

n_min,alincsi

movcx,num-1nt:mov

al,[si]

cmp

n_max,al

jgea1

mov

n_max,ala1:cmp

n_min,al

jlea2

mov

n_min,ala2:incsiloopntretmainendpcodeendsendmain

作業(yè):在字節(jié)型數(shù)據(jù)區(qū)buf

中存放著若干個有符號數(shù),編寫一個程序?qū)⒔y(tǒng)計其中的正數(shù)和負數(shù)的個數(shù),統(tǒng)計結(jié)果分別存放到p_num和n_num字節(jié)單元。

5.2.4子程序設計一、基本概念子程序又稱為過程,相當于高級語言中的過程和函數(shù)。在一個程序的不同部分,如果多次出現(xiàn)一些類同的程序段,它們在功能上和結(jié)構(gòu)形式上都相同,只是變量的賦值不同,此時就可以把這樣的程序段寫成子程序形式,以便需要時調(diào)用它。調(diào)用子程序的程序稱為主程序或調(diào)用程序。子程序結(jié)構(gòu)是實現(xiàn)模塊化程序設計的重要工具和手段。為什么要使用子程序?在前面用“

”號構(gòu)成三角形圖案的【例3-6】題中,有兩處使用了回車和換行功能的程序段,因此可以使用子程序使其簡化。

【例3-6】程序回顧:

DATA SEGMENTMESS DB‘Pleaseinputanumber:$’DATA ENDSCODE SEGMENTASSUMEDS:DATA,CS:CODEBEGIN:MOV AX,DATA MOVDS,AX LEA DX,MESS MOVAH,09H ;DOS功能調(diào)用,顯示字符串

INT21HKEYIN:MOVAH,1 INT21H ;從鍵盤取數(shù)

CMP AL,33H ;同“3”比較

JBKEYIN ;小于“3”重新輸入

CMPAL,39H ;同“9”比較

JAKEYIN ;大于“9”重新輸入

AND AL,0FH ;把ASCII碼轉(zhuǎn)換為二進制數(shù)

CBW ;把AL中字節(jié)數(shù)據(jù)擴展成字

MOV CX,AX ;該數(shù)作為外層循環(huán)數(shù)送CX

MOV AH,2 ;DOS中斷的2號功能調(diào)用

MOV DL,0DH ;0DH是“回車”的ASCII碼

INT 21H ;使光標回到所在行的行首

MOV DL,0AH ;0AH是“換行”的ASCII碼

INT 21H ;使光標換行

L2:PUSH CX ;外層循環(huán)計數(shù)值入棧保存

L1:MOV DL,‘

’ MOV AH,2 INT 21H ;在一行上循環(huán)打印“

LOOP L1

MOVAH,02H

MOV DL,0DH INT 21H ;光標回到行首

MOV DL,0AH INT 21H ;光標下移一行

POP CX ;外層循環(huán)計數(shù)值出棧

LOOP L2 ;在新行上循環(huán)打印“

MOV AH,4CH INT 21HCODE ENDS END BEGIN

┇ ;省略部分與例題4-9相同

AND AL,0FH ;把ASCII碼轉(zhuǎn)換為二進制數(shù)

CBW MOV CX,AX ;該數(shù)作為外層循環(huán)數(shù)送CX

CALL CRLF

;調(diào)用CRLF子程序

L2:PUSH CX ;外層循環(huán)計數(shù)值入棧保存

L1:MOV DL,‘

’ MOV AH,2 INT 21H LOOP L1 ;在一行上循環(huán)打印“

CALL CRLF

;調(diào)用CRLF子程序

POP CX ;外層循環(huán)計數(shù)值出棧

LOOP L2 ;在新行上循環(huán)打印“

MOV AH,4CH INT 21H;采用子程序結(jié)構(gòu)

;----以下是完成回車換行功能的子程序----CRLF PROC NEAR

MOV AH,2 ;DOS功能調(diào)用號送AH MOV DL,0DH ;0DH是“回車”的ASCII碼

INT 21H ;使光標回到所在行的行首

MOV DL,0AH ;0AH是“換行”的ASCII碼

INT 21H ;使光標換行

RET

CRLF ENDPCODE ENDS END BEGIN

二、子程序定義及其屬性子程序是用過程定義偽指令PROC和ENDP來定義的,其過程類型屬性的確定原則如下:調(diào)用程序和過程在同一代碼段中則使用NEAR屬性;調(diào)用程序和過程不在同一代碼段中則使用FAR屬性;主程序應定義為FAR屬性,因為程序的主過程看成是DOS調(diào)用的一個子程序,而DOS對主過程的調(diào)用和返回都是FAR屬性。此外,過程定義允許嵌套,即在一個過程定義中允許包含多個過程定義。

1、調(diào)用程序和子程序同在一個代碼段中,程序格式如下:

CODESEGMENT┇

MAINPROCFAR;主程序

┇CALLPGM1;子程序調(diào)用語句

┇ RETPGM1PROCNEAR;被調(diào)用的子程序

RETPGM1 ENDP

MAIN ENDPCODE ENDS

2、當調(diào)用程序和子程序不在同一代碼段時,其程序格式如下:

CODE1SEGMENT┇

SUB_PGMPROCFAR

;被調(diào)用的子程序

┇ RET SUB_PGMENDP┇

CODE1 ENDS

CODE2 SEGMENT ┇ CALL SUB_PGM

;子程序調(diào)用語句

CODE2 ENDS

三、寄存器的保護與恢復在程序設計中調(diào)用程序與子程序通常是獨立編寫的,因此它們所使用的一些寄存器經(jīng)常會發(fā)生沖突。如果調(diào)用子程序之前的某些寄存器內(nèi)容在子程序返回主程序后還要使用,而子程序又恰好使用了這些寄存器,那么這些寄存器的原有內(nèi)容就會遭到破壞,從而使程序運行出錯。為防止這種錯誤的發(fā)生,就必須對相關(guān)寄存器內(nèi)容進行保護,其處理方法有以下兩種。1.在主程序中實施保護

┇ PUSH BX ;保存BX內(nèi)容

PUSH CX ;保存CX內(nèi)容

CALL SUB1 ;調(diào)用子程序

POP CX ;恢復CX內(nèi)容

POP BX ;恢復BX內(nèi)容

2.在子程序中進行保護

SUB1 PROC NEAR PUSH BX ;保存寄存器內(nèi)容

PUSH CX ┇ ;子程序功能指令序列

POP CX ;恢復寄存器內(nèi)容

POP BX RETSUB1 ENDP

5.2.5DOS系統(tǒng)功能調(diào)用一、概述在匯編語言程序設計中,經(jīng)常要用到BIOS(BasicInput/OutputSystem)的一些軟中斷和DOS系統(tǒng)功能調(diào)用來擴充匯編語言的功能。系統(tǒng)功能調(diào)用是DOS為用戶提供的一組常用子程序,這些子程序大致分為設備管理、文件管理和目錄管理等幾類。這里主要介紹部分DOS系統(tǒng)功能調(diào)用,通過這些例子掌握其使用方法,關(guān)于BIOS中斷和其它DOS功能調(diào)用,可參閱其它參考書自學。二、DOS功能調(diào)用的使用方法

DOS功能調(diào)用是由中斷指令“INT21H”實現(xiàn)的,具體調(diào)用該中斷的哪一個功能由其功能號來指定。程序設計人員可不必了解中斷子程序的內(nèi)部結(jié)構(gòu)和細節(jié),只需按以下三步完成DOS功能的直接調(diào)用。

(1)入口參數(shù)送指定寄存器(2)功能號送AH

(3)INT21H發(fā)出中斷請求指令下面以數(shù)據(jù)的輸入/輸出功能為例,說明DOS功能調(diào)用的方法。

1.帶顯示鍵盤輸入(功能號01H)

調(diào)用格式: MOVAH,01H INT21H功能:計算機等待鍵盤輸入一個字符,若有字符輸入,則首先檢查是否為Ctrl+Break或Ctrl+C鍵,若是,則退出本次調(diào)用,否則將鍵值送入AL寄存器,同時把這個字符送屏幕顯示。入口:無出口:AL中存放鍵盤輸入的字符(ASCII碼)。

2.顯示字符(功能號02H)

調(diào)用格式: MOV DL,‘字符’(或字符的ASCII碼)

MOV AH,02H INT 21H

功能:顯示DL寄存器中的字符,在字符輸出時若是Ctrl+Break或

Ctrl+C,則退出本次調(diào)用。入口:DL寄存器存放要顯示字符的ASCII碼值。出口:無3.打印字符(功能號05H)調(diào)用格式: MOV DL,’字符’(或字符的ASCII碼)

MOV AH,05H INT 21H

功能:打印DL寄存器中的字符,在字符輸出時若有Ctrl+Break或

Ctrl+C,則退出本次調(diào)用。入口:DL寄存器存放要打印的ASCII碼值。出口:無

4.直接控制臺輸入輸出(功能號06H)

調(diào)用格式: MOV DL,X MOV AH,06H INT 21H功能:從標準輸入設備(如:鍵盤)輸入字符,也可以向屏幕輸出字符,但不檢查Ctrl+Break或Ctrl+C。(1)輸入方式當X=FFH時,表示從鍵盤輸入,若標志ZF=0,表示AL中為鍵入的字符值;若標志ZF=1,表示AL中不是鍵入的字符值,即無鍵按下。例如:

MOV DL,0FFH MOV AH,06H INT 21H

【例5-17】用DOS功能的6號調(diào)用循環(huán)檢查鍵盤,若有字符輸入則顯示輸入的字符,若遇到回車(0DH)則退出程序。

CODESEGMENT ASSUMECS:CODESTART:MOV DL,0FFH ;置字符輸入方式

MOV AH,06H ;6號功能調(diào)用

INT 21H ;

鍵盤檢查,讀輸入字符

JZSTART ;沒有字符輸入,再次檢查鍵盤

CMP AL,0DH ;輸入的是回車符嗎?

JZQQ ;是,退出程序(2)輸出方式當X

FFH時,表示向屏幕輸出,DL中為輸出字符的ASCII碼值。

例如: MOV DL,41H;向屏幕輸出字符“A” MOV AH,06H INT 21H

MOV DL,AL ;不是,顯示輸入字符

MOV AH,06H INT 21HJMP START ;繼續(xù)查看鍵盤

QQ: MOV AH,4CH INT 21HCODE ENDS END START5.無顯示字符輸入(功能號07H)調(diào)用格式: MOV AH,07H INT 21H功能:計算機等待鍵盤輸入一個字符,并將鍵值送入AL寄存器,但不把這個字符送屏幕顯示,也不檢查Ctrl+Break或Ctrl+C鍵。入口:無出口:AL是鍵盤輸入的字符(ASCII碼)。

6.無顯示字符輸入(功能號08H)

調(diào)用格式: MOV AH,08H INT 21H功能:計算機等待鍵盤輸入一個字符,若有字符輸入,則首先檢查是否為Ctrl+Break或Ctrl+C鍵,若是,則退出本次調(diào)用,否則鍵值送入AL寄存器,但輸入的字符不在屏幕上顯示。入口:無出口:AL中是存放鍵盤輸入的字符(ASCII碼)。7.字符串顯示(功能號09H)調(diào)用格式: MOV AH,09H INT 21H功能:在屏幕上輸出內(nèi)存中以$符作為結(jié)束標志的字符串,但不顯示$結(jié)束符。非顯示字符(如回車、換行)可以用它的ASCII碼插入字符串中間。入口:DS:DX指向字符串首地址出口:無

示例:

DATA SEGMENT BUF DB‘HOWDOYOUDO?$’ ;要顯示的字符串

┇ DATA ENDS CODE SEGMENT┇ MOV AX,DATA ;把數(shù)據(jù)段地址

MOVDS,AX ;送DS┇ LEA DX,BUF ;BUF偏移地址送DX MOV AH,09H ;9號功能調(diào)用

INT 21H┇ CODE ENDS

8.字符串輸入(功能號0AH)

調(diào)用格式: MOV AH,0AH INT 21H

功能:從鍵盤輸入字符串到內(nèi)存輸入緩沖區(qū),以回車鍵作為結(jié)束。入口:DS:DX指向內(nèi)存緩沖區(qū),緩沖區(qū)第一個字節(jié)是用戶設置的最大輸入字符數(shù)(1~225),含回車鍵碼。出口:緩沖區(qū)第二個字節(jié)存放用戶本次調(diào)用時實際輸入的字符數(shù)(不包括回車符),這個數(shù)由DOS返回時自動填入。從鍵盤上接收的字符從第三個字節(jié)開始存放,直到用戶輸入回車鍵為止,并將回車鍵碼(0DH)加在輸入字符串的末尾。所以設置緩沖區(qū)最大長度時,要比希望輸入的最多字符數(shù)多一個字節(jié)。若實際輸入的字符數(shù)超過緩沖區(qū)最大容量,后面輸入的字符被略去,且響鈴提示,直到輸入一個回車鍵才結(jié)束。

示例:最多輸入50個字節(jié)。

DATA SEGMENT

BUFDB51

;串長度為51個字節(jié),含回車碼

DB?

;存放實際輸入的字符個數(shù)

DB51DUP(?)

;定義51個字節(jié),含回車碼

┇ DATA ENDS CODE SEGMENT ┇ MOV AX,DATA MOV DS,AX ┇

MOV DX,OFFSETBUF

;DS:DX指向數(shù)據(jù)緩沖區(qū)BUF

MOV AH,0AH

;調(diào)用功能號送AH

INT 21H ┇ CODE ENDS

9.獲取中斷向量(功能號35H,P318)

調(diào)用格式: MOV AL,中斷類型號

MOV AH,35H INT 21H

功能:按指定的中斷類型號從中斷向量表中取出中斷向量。入口:AL寄存器存放待獲取中斷向量的中斷類型號。出口:中斷向量的段值和偏移量分別放在ES和BX中。10.設置中斷向量(功能號25H,P315)調(diào)用格式:MOVAL,中斷類型號;(新中斷向量放在DS:DX中)

MOVAH,25HINT21H

功能:將指定的中斷類型號在中斷向量表中的中斷向量設置成新指定的中斷向量。入口:AL存放中斷類型號,新中斷向量的段值和偏移量分別放在DS

和DX中。出口:無

下面進一步舉例說明DOS功能調(diào)的使用方法。【例】利用DOS功能調(diào)用實現(xiàn)人機對話。在屏幕輸出“Whoareyou?”然后把鍵盤輸入的信息送內(nèi)存數(shù)據(jù)緩沖區(qū)NAME中,并顯示輸入信息。(與P179的例7.1類似)

DATA SEGMENT NAM DB10,?,10DUP(?)

ASK DB‘Whoareyou?’,‘$’ DATA ENDS CODE SEGMENT ASSUMECS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX

MOV DX,OFFSETASK

;輸出字串首址送DX

MOV AH,09H

;9號功能調(diào)用

INT 21H

;輸出字串

MOV DX,OFFSETNAM ;輸入字串首址送DX MOV AH,0AH ;10號功能調(diào)用

INT 21H ;讀入以回車結(jié)束的字串

MOV SI,OFFSETNAM ;SI指向NAM單元

XOR AX,AX ;清AX MOV AL,[SI+1] ;輸入的字符數(shù)送AL ADD SI,AX ;使SI指向倒數(shù)第2個字符

MOV BYTEPTR[SI+2],’$’;在最后一個字符后添加$字符

MOV DL,0AH ;換行

MOV AH,02H INT 21H MOV DL,0DH ;回車

MOV AH,02H INT 21H MOV DX,OFFSETNAM+2;DX指向輸入內(nèi)容

MOV AH,09H INT 21H ;將讀入字串再輸出

MOV AH,4CH INT 21HCODE ENDS END START【例】將C盤USR子目錄中的MY.ASM文件變?yōu)殡[含屬性文件。

DATA SEGMENT F_NAMEDB‘C:\USR\MY.ASM’,0;ASCIZ串

DATA ENDS CODE SEGMENT ASSUMECS:CODE,DS:DATA BEGIN:MOV AX,DATA MOV DS,AX

MOV AH,43H ;43H號功能調(diào)用

MOV AL,01H ;1置(0取)文件屬性

MOVCX,02H ;02H為隱含屬性(注)

LEA DX,F(xiàn)_NAME;文件名首址送DX INT 21H ;修改文件屬性

MOV AH,4CH INT 21HCODEENDS END BEGIN

注:CX中第0位為1表示文件是只讀屬性,第1位為1表示隱含屬性,第2位為1表示系統(tǒng)文件,第3位為1表示卷標,第4位為1表示子目錄,第5位為1表示歸檔文件,第6至7位未用。(參見P320)END

【實驗,自學】

編制一個程序,將十進制數(shù)轉(zhuǎn)換為十六進制數(shù),要求從鍵盤取得一個十進制數(shù),然后把該數(shù)以十六進制形式在屏幕上顯示出來,再讀數(shù),再顯示,如此循環(huán),直到鍵入Ctrl+C為止。根據(jù)題意,用一個KEY_ASTOB子程序完成鍵盤輸入和十進制數(shù)到二進制數(shù)的轉(zhuǎn)換;用SPACE_2子程序完成空格;用BTOH_DISP子程序完成二進制到十六進制顯示;再用一個CR_LF子程序完成回車和換行。主程序和子程序之間參數(shù)傳遞使用寄存器BX。

KEY_ASTOB子程序說明:十進制數(shù)有若干位,而每輸入1位十進制數(shù)數(shù),原來已輸入的每一位數(shù)字都要向高位移一位,也就是擴大10倍,然后再把新輸入的數(shù)字加到個位上。在KEY_ASTOB子程序中采用的方法與它類似,每輸入一位數(shù)(ASCII碼)都要先把它轉(zhuǎn)換為二進制數(shù),每得到這樣一個新的二進制數(shù),原來已得到的二進制數(shù)就要乘10,然后再加上這個新的二進制數(shù),這樣得到的二進制數(shù)才能與已輸入的十進制數(shù)相當。通過分析本題程序編制如下:

DATA SEGMENTMESS1 DB‘Pleaseinputanumber:$’MESS2 DB07H,07H,08H,’$’ ;響鈴、退格

DATA ENDS CODESEGMENT ASSUME

CS:CODE,DS:DATA

;----

以下是主程序部分----

MAIN PROCFAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AXRP: CALL KEY_ASTOB CALL CR_LF CALL BTOH_DISP CALL CR_LF JMP RP MAIN ENDP

;----以下是KEY_ASTOB子程序----

KEY_ASTOBPROCNEAR LEA DX,MESS1 ;顯示提示信息

MOV AH,09H INT 21H MOV BX,0 ;BX存放輸入的數(shù)據(jù)

NEWCH: MOV AH,1 ;從鍵盤取一位數(shù)

INT 21H CMP AL,0DH JZ EXIT AND AL,0FH ;把ASCII碼變?yōu)槎M制數(shù)

JL ER ;若小于0(非數(shù)字)跳轉(zhuǎn)

CMP AL,9D ;同9比較

JG ER ;大于9(非數(shù)字)跳轉(zhuǎn)

MOV AH,0 ;為了把AL中的字節(jié)內(nèi)容擴展為字

XCHG AX,BX;交換數(shù)據(jù)后,新數(shù)在BX,原數(shù)在AX MOV CX,10D;十進制數(shù)10送CX MUL CX ;AX中的原數(shù)乘10,結(jié)果送AX XCHGAX,BX;乘10后的結(jié)果在BX,新數(shù)在AX ADD BX,AX;乘10后的原數(shù)和新數(shù)相加,結(jié)果送BX JMP NEWCH;跳轉(zhuǎn)后等待再次輸入數(shù)據(jù)

ER: MOV AH,09H;退格、響鈴后,重新輸入

LEA DX,MESS2 INT 21H JMP NEWCHEXIT: RET ;結(jié)束輸入和轉(zhuǎn)換,返回主程序KEY_ASTOBENDP

;----以下是BTOH_DISP子程序----

BTOH_DISP PROCNEAR MOV CH,4 ;外循環(huán)置數(shù),需轉(zhuǎn)換四組二進制數(shù)

ROT: MOV CL,4 ;內(nèi)循環(huán)置數(shù),每四位二進制數(shù)為一組

ROL BX,CL ;BX的內(nèi)容循環(huán)左移四位

MOV AL,BL AND AL,0FH ;屏蔽掉高四位

OR AL,30H ;轉(zhuǎn)換為ASCII碼

CMP AL,3AH ;同ASCII碼“10”比較

JL DISP ;小于10轉(zhuǎn)移

ADD AL,7H ;不小于10轉(zhuǎn)換成A~FDISP: MOV DL,AL MOV AH,2 INT 21H ;AL中的內(nèi)容送顯示

DEC CH ;外層循環(huán)數(shù)減1 JNZ ROT ;CH

0跳轉(zhuǎn)

MOV DL,‘H’ ;顯示字符H,表示是十六進制數(shù)

MOV AH,2 INT 21H RETBTOH_DISPENDP

;----

以下是CR_LF子程序----CR_LF PROC NEAR MOV DL,0DH ;0DH是“回車”的ASCII碼值

MOV AH,2 INT 21H MOV DL,0AH ;0AH是“換行”的ASCII碼值

MOV AH,2 INT 21H RETCR_LF ENDPCODEENDSENDMAIN

以下為自學內(nèi)容

MOVAH,2CHINT21H出口:

CH:CL:DH:DL=時:分:秒:1/100秒(十六進制)實時鐘信息的讀寫操作(1)

實時鐘信息的讀寫操作(2)

對存放在芯片RAM中的實時鐘信息進行存取,需使用兩個I/O端口:地址端口和數(shù)據(jù)端口,相應的端口地址分別是70H和71H。因此,對RTCMOSRAM芯片內(nèi)部的64個字節(jié)內(nèi)容讀寫操作時,要分兩步進行:1.讀操作(1)先把需讀出的RAM單元位移地址送到地址端口(070H)。(2)再從數(shù)據(jù)端口(07lH)讀出該單元的內(nèi)容。例1:要求讀取“星期幾”的日期信息,則其讀出操作的程序段如下:

MOVAL,6H;6H是存放“星期幾”的單元位移地址

OUT070H,AL;送地址端口

JMPSHORT$+2

;

I/O延時

INAL,

溫馨提示

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

評論

0/150

提交評論