微机原理及接口技术IV.ppt
第4章 汇编语言程序设计 本章学习目标通过本章的学习,应当掌握以下内容:了解汇编语言的基本知识和特点。熟悉汇编语言的程序结构、段定义以及语句的格式。掌握汇编语言常用伪指令的使用方法。熟练掌握汇编语言程序设计的基本方法:顺序结构、分支结构、循环结构和子程序结构。掌握程序设计中的宏指令和常用的系统功能的调用方法。,4、1 机器语言、汇编语言与高级语言程序设计语言通常分为3类:机器语言(Machine Language)汇编语言(Assembler Language)高级语言(High Level Language)4、1、1 机器语言和汇编语言1机器语言(1)机器指令机器指令是指用二进制编码的指令,以表示计算机所要进行操作数及操作对象(数据或数据地址)。(2)指令系统和机器语言指令系统是指特定计算机上机器指令的集合。机器语言是由指令系统以及机器指令的使用规则构成的。机器语言是计算机惟一能识别的语言,只有用机器语言描述的程序,计算机才能直接执行。,(3)机器语言的主要特点机器语言主要具有下列两个特点:机器语言与机器密切相关 机器语言设计程序非常困难,但容易实现高性能 2 汇编语言以助记符描述的指令称作汇编格式指令或符号指令,通常简称指令。指令和伪指令的集合及其程序设计规则便构成了汇编语言。用汇编语言编写的程序就是汇编语言源程序。4、1、2 汇编语言与高级语言机器语言和汇编语言都是面向机器的,是低级语言。高级语言在程序设计的简易性与代码的可移植性等方面有了质的飞跃。当然,用高级语言编写的源程序必须经过编译和连接,将其转变为可执行程序或借助于解释程序方可在计算机上运行。,汇编语言和高级语言的比较:,4、1、3 汇编与连接,1汇编程序 汇编是把汇编语言程序翻译成机器语言描述的目标程序的过程。汇编程序是完成汇编任务的程序。2连接程序 连接程序的主要功能是实现多个目标文件及库文件的连接,并完成浮动地位的重定位。从汇编语言源程序到可执行程序的生成过程如图所示。,汇编语言源程序,汇编,目标程序,连接,可执行程序,4、2 汇编语言源程序的结构4、2、1 汇编语言的语句格式汇编语言源程序中的每个语句可以由4项组成,格式如下name operation operand;comment名字项 操作项操作数项;注释项下面分别说明各项的表示方法。1名字项源程序中用下列字符表示名字:字母:AZ或az;数字:09;专用字符号:?、$;一般来讲,名字项可以是标号或变量。(1)标号:在代码段定义,后面跟冒号:它有三种属性:段、偏移及类型。,段属性:定义标号的段起始地址,在CX寄存器中。偏移属性:16位无符号数。类型属性:用来指出该标号是在本段内引用还是在其他段内引用的。(2)变量:变量在除代码以外的其他段中定义,后面不跟冒号。它也可以用LABLE或EQU伪操作来定义。变量经常在操作数字段出现。它也有段、偏移及类型三种属性。段属性定义变量的段起始地址,此值必须在一个段寄存器中。偏移属性变量的偏移地址是16位无符号数,它代表从段的起始地址到定义变量的位置之间的字节数。在当前段内给出变量的偏移值等于当前地址计数器的值,当前地址计数器的值可以用$来表示。类型属性变量的类型属性定义该变量所保留的字节数。,2操作项操作项可以是指令、伪操作或宏指令的助记符。3操作数项操作数项由一个或多个表达式组成,多个操作数项之间一般用逗号分开。4注释项注释项用来说明一段程序或一条或几条指令的功能,它是可有可无的。4、2、2汇编语言源程序的段定义段定义伪操作的格式如下:segment-name SEGMENT segment-name ENDS其中删节号部分,对于DS、ES和SS来说,一般是存贮单元的定义、分配等伪操作;对于代码段则是指令及伪操作。,此外,还必须明确段和段寄存器的关系,这可用ASSUME伪操作来实现,其格式为:ASSUME assignment,assignment其中 assignment 说明分配情况,其格式为:段寄存器名:段名其中段寄存器名必须是CS、DS、ES和SS中的一个,而段名则必须是由SEGMENT定义的段中的段名。4、2、.3 汇编语言源程序的结构汇编语言源程序的程序基本结构是段,一个汇编语言源程序由若干个代码段、数据段、附加段和堆栈段组成。段之间的顺序可以随意安排,通常数据段在前,代码段在后。任何可执行汇编语言程序至少要有一个代码段,通常还可能有数据段和堆栈段。每个段都有段首指令和段结束指令,段的内容介于这两条指令之间。,其一般结构如下:SSEG SEGMENT STACK 堆栈段的内容SSEG ENDSDSEG SEGMENT DATA 数据段的内容DSEG ENDSCSEG SEGMENT CODE 代码段的内容CSEG ENDS END 启动标号对于一般程序来说,定义太多的段只会增加程序设计的复杂性,通常需要一个代码段、一个数据段和一个堆栈段,有时可包含一个附加段。,1为什么要用ASSUME语句 指令 mov bl,xd mov xe,bl被汇编为mov bl,byte ptr0000hmov byte ptr es:0000h,bl其中,在变量xe前增加了段超越前缀ES:,这就是ASSUME的作用,也仅此而已。2设置段寄存器的初值(1)CS与IPCS与IP的初值不能在程序中显示设置,由系统自动设置为END后指定的起始地址。,(2)DS和ES、DS和ES的初值必须在程序中设置。设置方法如下:MOV AX,SEG NAME MOV DS,AX(3)SS与SPSS与SP初值的设置方法有下列两种:在程序中显示设置,类似于DS,例如:MOV AX,SSEGMOV SS,AXMOV SP,ST_TOP若堆栈段定义时给出了参数STACK,则连接器LINK自动将SS:SP指向栈底;若未定义堆栈段,则由系统指定堆栈,SS:SP也由系统自动设置。,例4.2:在数据段定义首地址为A的10个字符,将这10个字符以相反次序传送到附加段首地址为B的内存单元中。DSEG SEGMENTA DB 1234567890DSEG ENDSESEG SEGMENTB DB 10 DUP(?)ESEG ENDSCSEG SEGMENT ASSUME CS:CSEG,DS:DSEG,ES:ESEGSTART:MOV AX,DSEG MOV DS,AX,MOV AX,ESEG MOV ES,AXLEA SI,A LEA DI,B ADD DI,9 MOV CX,10MOVE:CLD LODSB STD STOSB LOOP MOVE MOV AH,4CH INT 21HCSEG ENDS END START,4、3 汇编语言的运算符,1算术运算符算术运算符主要包括+、*、/和MOD、等。其中MOD是指除法运算后得到的余数。语法格式为:expr1expr2等价于expr1+expr2。2逻辑运算符逻辑运算符主要包括AND、OR、XOR、NOT、SHR及SHL。逻辑操作符是按位操作的,它只能用于数字表达式中。3关系运算符关系运算符主要包括EQ(相等时为真)、NE(不相等时为真)、LT(小于时为真)、GT(大于时为真)、LE(小于或等于时为真)、GE(大于或等于时为真)等6种。,4数值回送(Value returning)操作符它有TYPE、LENGTH、SIZE、OFFSET、SEG 5种。这些操作符把一些特征或存储器地址的一部分作为数值回送。下面分别说明各个操作符的功能。(1)TYPE格式:TYPE Variable或label如果是变量,则汇编程序将回送该变量的以字节数表示的类型,DB为1,DW为2,DD为4,DQ为8,DT为10。如果是标号,则汇编程序将回送代表该标号类型的数值:NEAR为1,FAR为2。(2)LENGTH格式为:LENGTH Variable对于变量中使用DUP的情况,汇编程序将回送分配给该变量的单元个数。而对于其他情况则回送1。,(3)SIZE格式为:SIZE Variable其汇编的值为LENGTH Variable*TYPE Variable,即回送直接分配给该变量的总的字节数。(4)OFFSET格式为:OFFSET Variable或label汇编程序将回送变量或标号的偏移地址值。(5)SEG格式为:SEG Variable或label汇编程序将回送变量或标号的段地址值。5属性操作符属性操作符主要包括PTR、段操作符、SHORT、THIS、HIGH和LOW 6种。(1)PTR格式为:type PTR expression,PTR用来建立一个符号地址,但它本身并不分配存储器,只是用来对已分配的存储地址赋予另一种属性,使该地址具有另一种类型。(2)段操作符:用来表示一个标量、变量或地址表达式的段属性。例如,用段前缀指定某段的地址操作数MOV AX,ES:BX+SI。可见它是用段寄存器地址表达式来表示的。(3)SHORT用来修饰JMP指令中转向地址的属性,指出转向地址是在下一条指令地址127个字节范围之内。(4)THIS格式为:THIS attribute或type(5)HIGH和LOW称为字节分离操作符,它接收一个数或地址表达式,HIGH取其高位字节,LOW取其低位字节。,4.4 伪指令构成汇编语言源程序的语句主要包括两类:指令和伪指令。指令是在程序运行期间有CPU执行的,汇编后由对应的机器代码所取代。伪指令是不可执行的,它只是在源程序汇编期间由汇编器处理的命令,用来指示汇编器为数据分配内存空间,或者为汇编器提供源程序结束或段定义等信息。1、变量定义伪指令变量定义伪指令用来为数据分配内存空间,并设置相应内存单元的初始值,其形式为:变量名 变量定义符 操作数,操作数 变量名是一个符号地址,表示其后操作数的首地址,多个操作数构成一个数组。变量名是程序员给出的标识符,为可选项,给出变量名只是为了按名存取其对应的内存单元。,变量定义符主要包括下列几种:(1)DB(Define Byte):定义字节,后面的每个操作数占1个字节。(2)DW(Define Word):定义字,后面的每个操作数占1个字。(3)DD(Define DWord):定义双字,后面的每个操作数占2个字。(4)DQ(Define QWord):定义四字,后面的每个操作数占4个字。(5)DT(Define Tbyte):定义十字节,后面的每个操作数占10个字节。操作数可以为:(1)数值表达式;(2)ASC码字符串;,(3)地址表达式;(4)?(只保存内存空间,未定义初始值);(5)DUP 子句,其格式为:重复次数 DUP(操作数,操作数),DUP子句可以嵌套。2、符号定义伪指令符号定义伪指令的基本形式为:符号名 EQU 表达式符号名=常数表达式功能:给表达式指定一个等价的符号名。说明:(1)=后的表达式只能是常数,对于字符或字符串,在汇编时按整数处理。(2)EQU后的表达式可以是数值、字符串,甚至可以是寄存器名、指令的助记符等。,(3)EQU不能重复定义,而“=”伪指令可以重复定义,其作用域从定义点到重新定义之前。3、段定义伪指令汇编语言源程序由一个段或多个段组成,多数程序采用一个代码段、一个数据段和一个堆栈段。段定义由SEGMENT与ENDS伪指令实现,基本形式如下:段名 SEGMENT STACK 语句序列段名 ENDS4、程序开始和结束伪操作在程序的开始可以用NAME或TITLE为模块的名字,NAME的格式是:NAME module_name作为模块的名字。如果程序中没有NAME 伪操作,则也可使用TITLE伪操作,其格式为:TITLE text,表示源程序结束的伪操作的格式为:END 启动标号 其中标号指示程序开始执行的起始地址。如果多个程序模块相连接,则只有主程序要使用标号,其他子程序模块则只用END而不必指定标号。这里要说明两点:(1)其中关于建立过程的PROC和ENDP伪操作对将在以后的章节中说明。这里只要知道利用这一对伪操作把程序段分为若干个过程,使程序的结构更加清晰就可以了。(2)这里只定义了最基本的代码段和数据段,如果程序中还需要定义附加段和堆栈段,则定义的方式及建立段寄存器的方法是相同的,读者可自行设计。,5、对准伪操作(1)EVEN伪操作使下一个字节地址成为偶数。一个字的地址最好从偶地址开始,所以对于字数组为保证其从偶地址开始,可以在它前面用EVEN伪操作来达到此目的。例如:DATA_SEG SEGMENT EVEN WORD_ARRAY DW 100 DUP(?)DATA_SEG ENDS(2)ORG 表达式如常数表达式的值为n,则ORG伪操作可以使下一个字节的地址成为常数表达式的值n。其中表达式必须是一个可计算得到正整数的,数值范围在065535的表达式。,4、5 宏指令与条件汇编1宏定义和宏调用宏是源程序中一段有独立功能的程序代码。它只需要在源程序中定义一次,就可以我次调用它,调用时只需要有一个宏指令语句就可以了。宏定义是用一组伪操作来实现的。其格式是:macro name macro dummy parameter list(宏定义体)ENDM经宏定义定义后的宏指令就可以在源程序中调用。这种对宏指令的调用称为宏调用,宏调用的格式是:macro name actual parameter list当源程序被汇编时,汇编程序将对每个宏调用作宏展开。宏展开就是用宏定义体取代源程序中的宏指令名,而且有实元取代宏定义中的哑元。,下面我们用一个例子来说明宏定义、宏调用和宏展开的情况。例 用宏指令定义两个字操作数相乘,得到一个16位的第三个操作数,作为结果宏定义:MULTIPLY MACRO opr1,opr2,RESULT PUSH DX PUSH AX MOV AX,opr1 IMUL opr2 MOV RESULT,AX POP AX POP DX ENDM宏调用:,MULTIPLY CX,VAR,XYZBXMULTIPLY 240,BX,SAVE宏展开:+PUSH DX+PUSH AX+MOV AX,CX+IMUL VAR+MOV XYZBX,AX+POP AX+POP DX+PUSH DX+PUSH AX,+MOV SAVE,AX+POP AX+POP DX,2 宏指令举例例 宏定义可以无变元宏定义:SAVEREG MACRO PUSH AXPUSH BXPUSH CXPUSH DXPUSH SI PUSH DI ENDM,宏调用:SAVEREG宏展开则将宏定义体的内容全部列出。3、条件汇编汇编程序能根据条件把一段源程序包括在汇编语言程序内或者把它排除在外,这里就用到条件伪操作。条件伪操作的一般格式是:IF argument 自变量满足给定条件汇编此块 ELSE 自变量不满足给定条件汇编此块 ENDIF,自变量必须在汇编程序第一遍扫视后就成为确定的数值,条件伪操作中的表示条件如下:IF expression 汇编程序求出表达式的值,如此值不为0则满足条件IFE expression 如求出表达式的值为0则满足条件。IFDEF symbo1 如符号已在程序中定义,或者已用EXTRN伪操作说明该符号是在外部定义的,则满足条件。IFNDEF symbo1 如符号未定义或未通过EXTPN说明为外部符号则满足条件。IFB 如自变量为空则满足条件。IFNB 如自变量不为空则满足条件。,IFIDN,如果字符串和字符串相同,则满足条件。IFDIF,如果字符串和字符串不相同,则满足条件。4、6 基本结构程序设计一般说来,编制一个汇编语言程序的步骤如下:(1)分析题意确定算法。这一步是能否编制出高质量程序的关键,因此拿到题应该仔细地分析和理解题意,找出合理的算法及适当的数据结构,不应当急于的去写程序。(2)根据算法画出程序框图。这点对初学者特别重要,这样做可以减少出错的可能性。画图可以从粗到细把算法逐步地具体化。(3)根据框图编写程序。(4)上机调试程序。,程序有顺序、循环、分支和子程序4种结构形式。,4、6、1 顺序结构顺序程序设计,又叫直接程序设计。它是相对于分支程序和循环程序设计而言的。因此,可以说顺序程序是既不包含分支,又不包含循环的程序,顺序程序是从第一条指令开始,按其自然顺序,一条指令一条指令地执行,在运行期间,CPU既不跳过某些指令,也不重复执行某些指令,一直执行到最后一条指令为止。例:从键盘键入0至9中任一自然数X,求其立方值。求一个数的立方值可以利用乘法和查表方法来实现,在本例中利用查表方法来实现。构造一个立方表,事先将0至9的立方存放在表中,求0至9的立方值可直接从表中查出。,表存储单元分配:字节变量X存放键入的自然数X,字变量XXX中存放X的立方值。从表结构可知,X的立方值在表中的存放地址与X有如下对应关系:(TAB+2*X)=X的立方值源程序如下:STACK SEGMENT STACKDB 200 DUP(0)STACK ENDSDATA SEGMENTINPUT DB“PLEASE INPUT X(09):$”TAB DW 0,1,8,27,64,125,216,343,512,729X DB?XXX DW?DATA ENDS,CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK START:MOV AX,DATA MOV DS,AX MOV AH,9 LEA DX,INPUT INT 21H MOV AH,1 INT 21H AND AL,OFH MOV X,AL ADD AL,AL MOV BL,AL MOV BH,0 MOV AX,TAB BX,MOV XXX,AX MOV AH,4CH INT 21HCODE ENDS END START,4.6.2 分支结构1分支程序设计概述分支程序结构可以有两种形式,如图所示,判断条件,Y,N,判断条件,2、分支程序设计分支结构程序设计的关键在于准确地知道操作结果影响的标志位状态和正确地使用条件转移指令。根据对条件的判断而选择不同的处理方法是人的基本智能体现。例:设内存中有三个互不相等的无符号字数据,分别是放在ARG开始的字单元,编制程序将其中最大值存入MAX单元。分析:求三个无符号数中的最大值,只要把三个数据两两比较,用JA/JNB/JNA/JC等指令就可判断两数的大小,从而选出其中最大值。源程序如下:SSEG SEGMENT STACK STK DB 20 DUP(0)SSEG ENDS,DSEG SEGMENTARG DW 7138H,84A6H,29EHMAX DW?DESG ENDSCSEG SEGMENT ASSUME CS:CSEG,DS:DSEG,SS:SSEGFMAX:MOV AX,DSEG MOV DS,AX MOV SS,AX MOV SP,SIZE STK LEA SI,ARG MOV AX,SI MOV BX,SI+2 CMP AX,BX,JAE FMAX1MOV AX,BXFMAX1:CMP AX,SI+4JAE FMAX2 MOV AX,SI+4FMAX2:MOV MAX,AXMOV AH,4CHINT 21HCSEG ENDS END FMAX4、6、3 循环程序设计1循环程序设计概述有时我们会需要能按一定规律,多次重复执行的一串语句,这类程序叫循环程序。,循环程序一般由四个部分组成:(1)循环初值部分:这是为了保证循环程序能正常进行循环操作而必须做的准备工作。循环初值分两类:一类是循环工作部分的初值,别一类是控制循环结束条件的初值。(2)工作部分:即需要重复执行的程序段。这是循环的中心,称之为循环体。(3)修改部分:按一定规律修改操作数地址及控制变量,以便每次执行循环体时得到新的数据。(4)控制部分:用来保证循环程序按规定的次数或特写条件正常循环。,例:已知道有N个元素存放在以BUF为首址的字节存储区中,试统计其中负元素的个数。显然,每个元素为一个8位有符号二进制数。统计其中负元素的个数的工作可用循环程序实现。存储单元及寄存器分配如下:BX:BUF存储区的地址指针,初值为BUF的偏移地址,每循环一次之后,其值增1。CX:循环计数器,初值为BUF区中元素的个数N,每循环一次之后,其值减1。AX:用来记录负元素的个数,初值为0。字变量R用来存放负元素的个数。,源程序如下:STACK SEGMENT STACKDB 200 DUP(0)STACK ENDSDATA SEGMENT BUF DB-2,5,-3,6,100 DB 0,-20,-9,8,-110,20N=$-BUFR DW?DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN:MOV AX,DATA MOV DS,AX,LEA BX,BUF MOV CX,N MOV AX,0LOPA:CMP BX,BYTE PTR 0 JGE NEXT INC AXNEXT:INC BX DEC CX JNE LOPA MOV R,AX MOV AH,4CH INT 21HCODE ENDS END BEGIN,2、循环程序设计(1)循环的控制方法下面介绍最常见的两种控制方法:计数控制和条件控制。,计数控制当循环次数已知时,通常使用计数控制法。假设循环次数为n,常常用以下三种方法实现计数控制和条件控制先将循环次数n送入循环体计数器中,然后,每循环一次,计数器减1,直至循环计数器中的内容为0时结束循环。如:MOV CX,n;循环初值部分LOOPA:;工作部分;修改部分 DEC CX;控制部分 JNZ LOOPA:,其中工作部分、修改部分被重复执行n次,即当(CX)=n,n-1,1时,重复执行循环体,当(CX)=0时,结束循环。先将循环次数的负值送入循环计数器中,然后每循环一次,计数器加1,直至计数器中的内容为零时结束循环。例如:MOV CX,n;循环初值部分LOOPA:;工作部分;修改部分 INC CX;控制部分 JNZ LOOPA,其中工作部分、修改部分被重复执行n次,即当(CX)=n,(n1),1时重复执行,当(CX)=0时结束循环。,先将0送入循环计数器中,然后每循环一次,计数器加1,直到循环计数器的内容与循环次数n相等时退出循环。例如:MOV CX,0;循环初值部分 LOOPA:;工作部分;修改部分 INC CX;修改部分 CMP CX,n JNE LOOPA其中工作部分、修改部分重复执行n次,即当(CX)=0,1,n1时重复执行,当(CX)=n时结束循环。,条件控制有些情况下,循环次数事先无法确定,但它与问题的某些条件有关。这些条件可以通过指令来测试。若测试比较的结果表明满足循环条件,则继续循环,否则结束循环。,例:统计AX寄存器中1的个数,并将结果存放在CL寄存器中。MOV CL,0 L:AND AX,AX JZ EXIT SAL AX,1;将AX中的最高位移入CF中 JNC L;如果CF=0,转L INC CL;如果CF=1,则(CL)+1CL JMP L;转L处继续循环 EXIT:,2、单重循环程序设计所谓单重循环指循环体内不再包含循环结构。下面分循环次数已知和未知两种情况讨论其程序设计方法。(1)循环次数已知的循环程序设计对于循环次数已知的情况,通常采用计数控制方法来实现循环。(2)最大循环次数未知的循程序设计对于循环次数未知的情况,常用条件来控制循环。3、多重循环程序设计多重循环即循环体内套有循环。设计多重循环程序时,可以从外层循环到内层循环一层一层地进行。,4、6、4 子程序设计1子程序设计概述,(1)子程序定义伪指令子程序定义伪指令有两条:PROC和ENDP使用这两条子程序定义伪指令所定义的子程序的一般格式如下:PN PROC NEAR/FAR;说明过程开始;过程体PN ENDP;说明过程结束说明:伪指令一前一后,如同过程体的语句括号,说明过程的开始与结束,中间为过程体。这两条伪指令必须成对出现。N为过程名,有以标识不同的过程。过程名的命名原则与标号相同,一般在程序设计风格上有所讲究。给过程命名时最好用一个使人容易理解的过程名。,过程体即为一段独立的程序,是完成子程序功能的程序主体。除了不能使用HLT等引起停机的指令而必须使用返回指令作为逻辑上最后一条指令之外,与以前所讲的程序设计没有任何区别。也就是说,过程体中可以使用除引起停机的指令以外的任何指令。EAR和FAR分别指出所定义的过程是近过程还是远过程。近过程只允许段内调用,即在转返过程中保持当前CS不变,只允许本段内程序使用。NEAR和FAR都不写时默认所定义的过程为近过程。,例:在代码段SEG1段定义两个过程SUB1和SUB2,并使SUB1只为本段程序调用,SUB2可为其他代码段程序调用。程序的过程定义部分如下所示:SEG1 SEGMENT PUBLIC,SUB1 PROC NEAR SUB1 ENDPSUB2 PROC FAR SUB2 ENDPSEG1 ENDS(2)调用指令CALL(3)返回指令RET2、子程序程序设计(1)子程序的嵌套我们已经知道,一个子程序也可以作为调用程序去调用另一个子程序,这种情况就称为子程序的嵌套。嵌套的层次不限,其层数称为嵌套深度。,(2)递归子程序在子程序嵌套的情况下,如果一个子程序调用的子程序就是它自身,这就称为递归调用。这样的子程序称为递归子程序。递归子程序对应于数学上对函数的递归定义,它往往能设计出效率较高的程序,可完成相当复杂的计算,因此它是很有用的。例如阶乘函数,常常使用递归子程序的设计方法。,4、7 常用系统功能调用和BIOSBIOS是BASIC INPUT/OUTPUT SYSTEM的缩写,即基本输入/输出系统,指固化在ROM中的一组程序,以称ROM BIOS。BIOS提供了最低,最直接的硬件控制,是硬件与软件之间的接口。BIOS主要包括以下一些功能。,(1)系统自检及初始化。例如,系统加电启动时对硬件进行检测;对外部设备进行初始化;设置中断向量;引导操作系统等。(2)系统服务。为操作系统和应用程序提供系统服务,这些服务主要与I/O设备有关,如读取键盘输入等。为了完成这些操作,BIOS必须直接与I/O设备打交道,它通过端口与I/O设备之间传送数据,使应用程序脱离具体的硬件操作。(3)硬件中断处理。提供硬件中断服务程序。,下面简要介绍一些较常用的DOS与BIOS服务。1 DOS系统调用MS DOS使用中断号21H作为系统说明,为程序员提供了上百种系统服务功能。,对这些功能的调用步骤如下:(1)由AH给出功能号;(2)根据相应功能的要求,设置入口参数。入口参数是子程序运行所需要的数据,DOS系统功能调用的入口参数通常是放在指定的内部寄存器器中,少数功能调用也可以没有入口参数;(3)执行中断指令INT 21H;(4)分析和使用出口参数。,下面详细介绍字符与字符串的输入/输出的调用方法,(1)键盘读入一个字符功能号:01H。入口参数:无。出口参数:AL=输入字符的ASCII码。功能:等待从键盘读入一个字符,将其ASCII码送入AL,同时将字符显示在屏幕上。,调用方法:MOV AH,1 INT 21H说明:输入一个字符后,不需要回车。若只输入回车,则AL=0DH。(2)显示一个字符功能号:02H。入口参数:DL=要显示字符的ASCII码。,出口参数:无。功能:在当前光标位置显示DL中的字符,光标右移。调用方法示例:MOV DL,A;显示字符AMOV AH,2INT 21H,(3)显示一个字符串功能号:09H。入口参数:DS:DX=欲显示字符串在内存的首地址,且字符串必须以$(24H)作为结束符。出口参数:无。功能:在当前光标位置,显示由DS:DX所指的、以$结尾的字符串,且光标右移。其中,$不算在显示的字符串之内。(4)从键盘读入一个字符串功能号:0AH。入口参数:DS:DX=输入缓冲区首地址。出口参数:无。功能:从键盘读入一个字符串,存放DS:DX所指的缓冲区。,下面介绍一下其他功能:(1)AH=25H:设置中断向量入口参数:AL=中断号。DS:DX=中断向量。功能:将AL所指中断号的中断向量设置为DS:DX。(2)AH=35H:获取中断向量入口参数:AL=中断号。出口参数:ES:BX=中断向量。功能:将AL的指中断号的中断向量由ES:BX返回。(3)AH=31H:程序终止并驻留内存入口参数:AL=返回码。DX=驻留内存的节数(1字=16字节)。功能:终止程序执行,全由DX所确定的一部分代码工数据仍留在内存中。,2、BIOS服务BIOS提供了访问主要I/O设备的服务程序。,下面主要介绍显示器输出服务和键盘输入服务。,(1)INT 10H:显示器输出INT 10H包含了与显示器有关的功能,可用来设置显示方式,设置光标大小和位置,显示字符等。AH=0AH:显示字符入口参数:AL=欲显示字符的ASCII码。AH=0EH:显示字符入口参数:AL=欲显示字符的ASCII码。功能:类似于0AH功能,但显示字符后,光标随之移动,并可解释回车,换行和退格等控制符。,(2)INT=16H:键盘输入AH=0:从键盘读一键出口参数:AL=ASCII码,AH=扫描码。功能:从键盘读入一个键后返回,按键不显示在屏幕上。对于无相应ASCII码的键,如功能键等,AL返回0。扫描码是表示按键所在位置的代码,有关细节将在以后讨论。AH=1:判断是否有键可读出口参数:若ZF=0,则有键可读,AL=ASCII码,AH=扫描码;否则,无键可读。AH=2:返回变换键的当前状态出口参数:AL=变换键的状态。,例:读键盘输入,显示其中的ASCII字符,按回车键退出,源程序如下。CSEG SEGMENT PARA PUBLIC CODE ASSUME CS:CSEGSTART:READNEXT:MOV AH,0 INT 21H CMP AL,0DH JZ READNEXT MOV AH,0EH INT 10H JMP READNEXT EXIT:MOV AH,4CH INT 21H CSEG ENDS END START,习 题1.假设VAR1和VAR2为字变量,LAB为标号,试指出下列指令的错误之处:(1)ADD VAR1,VAR2(2)SUB AL,VAR1(3)JMP LABSI(4)JNZ VAR1(5)JMP NEAR LAB2.画图说明下列语句所分配的存储空间及初始化的数据值。(1)BYTE_VAR DB BYTE,12,12H,3 DUP(0,?,2 DUP(1,2),?)(2)WORD_VAR DW 5 DUP(0,1,2),?,5,BY,TE,256H,3.假设程序中的数据定义如下:PARTNO DW?PNAME DB 16 DUP(?)COUNT DD?PLENTH EQU$PARTNO问PLENTH的值为多少?它表示什么意义?4.有符号定义语句如下:BUF DB 1,2,3,123EBUFF DB 0L EQU EBUFFBUF 问L的值为多少?5.假设程序中的数据定义如下:LMAME DB 30 DUP(?)ADDRESS DB 30 DUP(?),CITY DB 15 DUP(?)CODE_LIST DB 1,7,8,3,2(1)用一条MOV指令将LNAME的偏移地址放入AX。(2)用一条指令将CODE_LIST的头两个字节的内容放入SI。(3)用一条伪操作使CODE_LENGTH的值等于CODE_LIST域的实际长度。6.试编写一个汇编语言程序,要求对键盘输入的小写字母用大写字母显示出来。7.把三个连续存放的正整数,按递增次序重新存放在原来的三个存储单元中。8.编写程序,从键盘接收一个小写字母,然后找出它的前导字符和后继字符,并按顺序输出这三个字符。,9.试编写一程序,比较两个字符串STRING1和STRING2所含字符是否完全相同,若相同则显示“match”,若不同则显示“No match”。10.试编写一个汇编语言程序,要求从键盘接收三个16进制数,并根据对三个数的比较显示出如下信息:(1)如果三个数都不相等则显示0;(2)如果三个数有两个数相等则显示1;(3)如果三个数都相等,则显示2。11.编写程序,将一个包含20个数据的数组N分成两个数组:正整数组P和负整数组M,并分别把这两个数组中数据的个数显示出来。12.试编写一个程序,要求从键盘上接收一个4位的16位进制数,并在终端上显示出与它等值的二进制数。,13.从键盘输入一系列以$为结束符的字符串,然后对其中的非数字字符计数,并显示出计数结果。14.数据区保存有10个学生的姓名及其成绩,要求编写一程序将每个学生的成绩转换成6个等级。(A:90100;B:8090;C:7079;D:6669;E:6065;F:60分以下)。15.编写一段程序,如果字节变量TESTONE和TESTTWO相等,则调用ALLSAME子程序,否则调用NOSAME子程序。16.写一段子程序SKIPLINE,完成输出空行的功能,空出的行数AX寄存器中。17.试编写一个子程序。使它能接收从键盘输入的十进制数(如益出则指示出错),并将它转换为二进制数存放在DATA单元中。,18.编写一条宏指令CLRB:完成用空格符将一字符区中的字符取代的工作。字符区首地址及其长度为变元。19.定义宏指令FINSUM:比较两个数X和Y,若XY,则执行SUMX+2Y,否则执行SUM2X+Y。20.编写一段程序完成一段功能:如变元X=VT55,则汇编MOV TERMINAL,0;否则汇编MOV TERMINAL,1。,