微机原理第三章汇编语言程序设计课件

PPT
  • 阅读 51 次
  • 下载 0 次
  • 页数 132 页
  • 大小 847.001 KB
  • 2022-11-24 上传
  • 收藏
  • 违规举报
  • © 版权认领
下载文档40.00 元 加入VIP免费下载
此文档由【小橙橙】提供上传,收益归文档提供者,本网站只提供存储服务。若此文档侵犯了您的版权,欢迎进行违规举报版权认领
微机原理第三章汇编语言程序设计课件
可在后台配置第一页与第二页中间广告代码
微机原理第三章汇编语言程序设计课件
可在后台配置第二页与第三页中间广告代码
微机原理第三章汇编语言程序设计课件
可在后台配置第三页与第四页中间广告代码
微机原理第三章汇编语言程序设计课件
微机原理第三章汇编语言程序设计课件
还剩10页未读,继续阅读
【这是免费文档,您可以免费阅读】
/ 132
  • 收藏
  • 违规举报
  • © 版权认领
下载文档40.00 元 加入VIP免费下载
文本内容

【文档说明】微机原理第三章汇编语言程序设计课件.ppt,共(132)页,847.001 KB,由小橙橙上传

转载请保留链接:https://www.ichengzhen.cn/view-44810.html

以下为本文档部分文字说明:

第三章汇编语言程序设计第一节机器语言、汇编语言与高级语言一、机器语言与汇编语言计算机完成任何一个特定的功能都是通过执行特定的程序来实现的,程序是一系列指令组成的,计算机通过对每条指令的译码和执行来完成一系列操作。计算机最终能理解并执行的是以二进制代码表示的机器语言

。例3-1在内存中有一个数据块,其首地址为Buffer(3000H:0200H),其中存放16位的符号数20个。现要找出其中的最大值,并将其存入MAX字单元(其偏移地址为0228H)。借助8086汇编指令我们可以编写出如下程序:;exm3_1findthelargestnumberandstore

inthemaxunitMOVAX,3000HMOVDS,AXMOVSI,0200HMOVCX,14HDECCXMOVAX,[SI]CHKMAX:ADDSI,2CMP[SI],AXJLENEXTMOVAX,[SI]NEXT:

LOOPCHKMAXMOV[0288H],AXINT20H汇编以后机器码在内存中的形式如表3-1所示。表中第三列是汇编语言指令,它是用便于记忆的符号和格式来表示每一条实际的机器指令代码。用机器语言来编写程序很不直观,也是不现实的,特别是对于复杂问题。

PC机有专门的汇编程序,可以用汇编语言直接编程。二、汇编语言与高级语言汇编语言程序设计的基本单位仍然是机器指令,只是采用助记符表示,便于人们记忆。因此汇编语言对机器的依赖性很大,称为面向机器的语言。每种机器都有它

专用的汇编语言,在一种机器上用的汇编语言程序很难搬到另一种机器上使用,即不具备通用性和可移植性。汇编语言程序设计员必须对机器的硬件及软件资源有足够的了解才能设计程序。尽管如此,各种汇编语言在基本原理、基本概念和基本编程方法等方面是相同或相近的。高级语言

,如BASIC、FORTRAN、C语言等是进一步发展了的计算机语言。它们是面向过程的语言,不依赖于机器,因而有很好的通用性和可移植性,而且用高级语言设计具有很高的程序设计效率。高级语言优点很多,还要学习汇编语言的理由如下:(1)汇编语

言仍然是各种系统软件(如操作系统)设计的基本语言。虽然有人用C语言来编写系统软件,但是要将它翻译成机器语言,还必须用到汇编语言。(2)用汇编语言编写的程序一般比用高级语言编写的程序执行得快,且所占内存较少。(3)在许多实时控制系统中,高级语言并不完全适合,汇编语言就是不

可缺少的了。特别是在直接有效地利用机器硬件功能方面,比如中断等就都少不了汇编语言。(4)用高级语言开发中,有时需要编写一些非标准过程,而高级语言可能并不支持。这时就需用汇编语言来补充高级语言在某些特定领域中的功能不足。(5)学习汇编语言对于学习

计算机硬件组成及工作原理是十分重要的。三、汇编与连接用汇编语言设计程序首先应根据任务编写汇编语言源程序,文件类型一般标为ASM文件。汇编语言源程序编写有许多规则和方法,本章将予以介绍。可以用各种文本编辑软件建立源文件,如全屏幕编辑软件EDIT,还有WORD等,ASM文件采用ASCII码。通常文件

名的后缀是.ASM。汇编语言源程序必须经过翻译才能变为二进制机器代码。在计算机中完成这种翻译工作的软件叫汇编程序或汇编器(Assembler)。MASM.EXE就是汇编程序。如果源程序名为:SAMPLE.ASM则用命

令:C:>MASMSAMPLE.ASM就可产生目标程序,文件类型一般标为OBJ。为了便于程序调试,同时还产生列表文件,一般标为LST。目标文件一般还不是可执行的程序,目标文件并没有最终解决机器的寻址问题。程序究竟装

在内存的哪个区域?目标文件没有指定。另外,多个不同的目标文件以及库文件LIB可以组合在一起形成一个更大的文件。连接装配程序LINK.EXE则用来把指定的目标文件和库文件组装成一个完整的程序文件,并且完成相对地址的调整和对变量引用的处

理。在汇编后再用LINK命令:C:>LINKSAMPLE则产生SAMPLE.EXE,这是一个可执行文件。EXE文件除了程序、数据等代码之外,还包含一个文件头。这个文件头也称程序段前缀PSP,占256个字节。文件头中包含了操作系统中的装入程序在把该EXE文件装入内存时所需要的有关信息,如重定

位表和初始化有关段寄存器信息等。PSP的头两个字节是一条INT20H指令,即返回DOS指令。当一个用户程序运行结束时,可以通过把控制返回给PSP中的这条指令而终止自已的进程。这是由用户程序返回操作系统的传统方法。当DOS加载一个可执行文件的程序代码到内存中去

时,它首先为该程序建立一个程序段前缀PSP,然后把可执行的程序代码加载到PSP后续的地址上。(即CS指向地点),而DS和ES初始化在PSP的起始地址。DOS装入EXE文件后的内行分配如图所示。第二节汇编语言源程序的结构如果把例3-1改写为标准的汇编语言源程

序,就可以用MASM命令进行汇编,则源程序如下:;exm3_1.asmfindthelargestnumberand;storeinthemaxunitdatasegmentorg0200hbufferdw

0,1,-5,10,256,-128,-100,45,6dw3,-15,-67,39,4,20,-1668,-32766dw32765,-525,300countequ($-buffer)/2maxdw?dataendsstacksegmentstack

‟stack‟db100dup(‟s‟)stackendscodesegmentpara‟code‟assumecs:code,ds:data,ss:stackstaprocfarpushdsxorax,axpushaxmovax,datamovds,ax

leasi,buffermovcx,countdeccxmovax,[si]chkmax:addsi,2cmp[si],axjlenextmovax,[si]next:loopchkmaxmovmax,axretstaendpcodeendsend

sta一、汇编语言的语句格式下面分析汇编语言源程序的结构。汇编语言包含两类语句:CPU指令语句和汇编语言伪指令语句。指令语句指定CPU做什么操作,如第二章所述;伪指令语句指定汇编器作何种操作,这是这一章要学习的。

指令语句都有对应的机器码,而伪指令语句一般不产生机器码(只有少数一些数据定义伪指令会产生机器代码)。1.指令语句的格式汇编语言的CPU指令语句格式如下:[label:]memonic[operand][,operand][;comments]标号域助记符域操作数域注释域四个域中只有助记符域

是必不可缺的,其他的域都是可选的。助记符域是指令的操作码助记符,如MOV、ADD、SUB等等。助记符域与操作数域之间至少应留有一个空格。两个操作数之间要有逗号分开。标号一般为转移指令提供目标地址的符号名,例如上例中的CHKMAX。程序员不必去计算相对转移的地

址偏移量,汇编器会自动完成这一工作。标号后面跟一个冒号。伪指令前的名字不能后跟冒号。注释域以分号打头。汇编语言中的标号或名字或其他变量名必须是由字母或特殊字符打头的字母数字串,中间不能有空格。合法的字符包括:字母:A~Z或a~z数字:0~9特殊字符:问号(?)、圆点(.)、@、下

横线(_)和美元符号($),圆点只能作为第一个字符。标号和名字的长度不超过31个字符,超过部分均被删去。2.汇编伪指令的格式伪指令是针对汇编程序的命令。它可以用来定义段和过程、定义语句、分配内存空间以及完成各种与程序设计有关的

重要说明。汇编伪指令也有四个域:[名字]伪指令[操作数][注释]一般来说,只有伪指令域是必须的。对于某些伪指令,名字域也是必须的,但是要注意的是名字域后面不能用冒号(:)相随。域与域之间用空格隔开。伪指令的操作数域是可选的,它可以有多个操作数,只受行长度的限制。有的伪指令

操作数域部分的各操作数之间要求用逗号(,)分开,而有些伪指令则要求用空格分开,必须严格遵循有关规定。二、汇编语言源程序的段定义汇编语言源程序的段定义与内存的分段组织直接相关。典型的程序包含代码段、数据段和堆栈段。SEGMENT和ENDS伪指令用

于定义各种段。它们的语句格式如下:段名字SEGMENT[可选项](段模块)段名字ENDS段名字必须在两处出现,而且必须一致。SEGMENT和ENDS必须成对出现。SEGMENT定义一个段的开始,ENDS定义一个段的结束。SEGMENT语句可以有三种可选项:定位类型、连接

方式和类别。可选项之间用空格符或制表符TAB分开。格式如下:段名SEGMENT[定位类型][连接方式][„类别’]1.定位类型定位类型指明该段进入内存时从何种类型的边界开始。有四种定位类型:PAGE、PARA、WORD、BYTE。起始地址分别是:PAGE:××××××××××××000000

00BPARA:××××××××××××××××0000BWORD:×××××××××××××××××××0BBYTE:××××××××××××××××××××B分别表示以页、段、字、字节为起始地址。若缺省则

隐含为PARA。2.连接方式连接方式告诉链接程序本段与其他段的关系。共有六种方式。NONE表示本段与其他段在逻辑上没有关系,每段都有自己的基址。这是隐含方式。PUBLIC链接程序把本段与同名同类别的其

他段连接成一个段。STACK表示此段为堆栈段。连接时将所有STACK连接方式的同名段连接成一个段。程序中必须至少有一个STACK段,否则用户必须指令初始化SS和SP;若有多个,初始化时SS指向第一个STACK段。C

OMMON链接程序为本段和同名同类型的其他段指定相同的基址,因而本段将与同名同类别的其他段相覆盖。段的长度为最长的COMMON段的长度。AT表达式链接程序把本段装在表达式的值所指定的段地址上。例:AT1234H,

该段的首地址为12340H。MCODESEGMENTAT2050H;该段从20508H开始,ORG0008H;ORG伪指令给定偏移地址值START:MOVAX,0;该指令与段基址偏移8个字节………….MCODEEND

SMEMORY链接程序把本段定位在其他所有同名段之上(即地址较大的区域)。若有多个MEMORY段,则第一个按MEMORY方式处理,其余均按COMMON方式处理。3.类别类别必须用单引号括起来。类别指定同样只在模块连接时才需要。一

般对于堆栈段总定义类别为‘STACK‟;对代码段通常指定类型为‘CODE‟;对数据段则指定为‘DATA‟。如果一个程序不准备和其他程序组合,也可以不指定类别。类别名可由用户任意设定。链接程序把类别名相同的段(段名未必相同)放在连续的存储

区间内。但仍为不同的段(连接方式为PUBLIC、COMMON的段除外)。在前面例子中的堆栈段定义如下:STACKSEGMENTPARASTACK„STACK‟堆栈段名定位连接方式类别在堆栈段里一般只要简单地定义一下堆栈段空间大小就行了。如DB100DUP(?)语句为堆栈

分配了100个字节的空间。堆栈空间的大小取决于程序如何使用堆栈。最大不能超过64KB。定义堆栈空间时还可以给字节以初始化,例如:DB100DUP(„STACK‟)不仅分配了500个字节的堆栈空间。而且还把这个空间初始化为重复100次的’STACK‟字

符串。其目的是为了在查看内存分配以调试程序时可以方便地找到堆栈空间。一般应直接定义为字空间:DW20DUP(?)三、汇编语言的过程定义代码段的内容主要是程序的可执行码。一个代码段可以由一个或几个过程(子程序)组成

,仅由一个过程组成的代码段其形式如下:段名SEGMENT过程名PROCFAR;过程定义语句……;过程体RET过程名ENDP;过程定义结束段名ENDS过程定义由伪指令PROC和ENDP完成。PROC后面的参数指定该过程的属性。属性为FAR代表这个过程是段际过程,属性为NEAR表示该过

程是段内过程,省缺时代表NEAR过程。一个程序的主程序通常是FAR过程,如前面例子。但一般主程序不写成过程的形式,举例见后。PROC和ENDP必须成对出现,而且前面的过程名必须一致。例如对上例中过程可定义为STA,则有:STAPROCFAR……RE

TSTAENDPRET在FAR过程中被汇编为段际返回指令,在NEAR过程被汇编为段内返回指令。两者的机器码是不同的。同一段内的过程一般总是定义为NEAR过程,过程一经定义就可以用CALL语句调用:CALL过程名如果过程名是FAR属性,则是段际调

用,产生双字构成的目标地址,并将双字的返回地址压入堆栈。四、汇编语言的段寻址用SEGMENT定义完各段后,还要用ASSUME伪指令来说明段寄存器与段名之间的对应关系。ASSUME语句的一般格式为:ASSUME段寄存器名:段

名[,…]其中段寄存器有CS、DS、ES和SS。每个指定之间用逗号分开。上例中ASSUME语句为:ASSUMESS:STACK,CS:CODE,DS:DATA由于该例中没有用到ES,可以不写。ASSUME语句必须写在代码段中,一般情况下放在码段定义语句之后。ASSUME语句给出了段名与段

寄存器的对应关系,但并没有真正给段寄存器赋值。段寄存器的赋值还要由程序本身来完成,例如上例中用了:MOVAX,DATAMOVDS,AX给DS赋值。注意第一条指令:当MOV指令源操作数出现段名时,把段基址送给目的操作数,这是传送指令中的一

个特殊情况。为什么只对DS赋值呢?这是因为DOS环境下运行程序时,DOS的装入程序已对CS:IP和SS:SP作了正确的初始化,而DS、ES初始化为程序段前缀PSP的起点,而非用户所需的地址,见图3-1。五、标准程序前奏DOS加载一个外部(EXE

)文件时首先要建立一个PSP,其头两个字节是一条INT20H指令。执行INT20H指令是把控制返回给DOS的传统方法。由于DOS的装入程序在加载一个程序时把DS和ES定位在PSP的起点上,于是我们应在程序一开始通过下面三

条指令把PSP的起点地址压入堆栈:PUSHDSSUBAX,AXPUSHAX这样当程序执行到最后一条RET指令时,它将从堆栈顶部弹出PSP的起点地址送CS:IP,使得INT20H指令得以执行,从而把控制权交还给DOS。因此常把这三条指令称

为标准程序前奏。六、汇编结束语句END汇编语言源程序的最后一个语句是汇编结束语句,即END语句,其格式是:END表达式其中表达式必须产生一个存储器地址,这个地址是当程序执行时,第一条要执行的指令的地址。

在上例中,结束语句为:ENDSTASTA是过程名,也即是第一条要执行的指令的地址。END语句通知汇编程序,汇编到此结束。END后面的表达式是可选的。如果一个模块是主模块,那么表达式通常是过程名,或者是第一条指令前

的标号,它告诉汇编程序程序的入口点所在。如果不是主模块,而只是要把它和另外一个主模块连接,那么就应该用不带表达式的END语句。七、汇编语言源程序结构我们看到一个汇编语言的源程序可以由几个段组成,其中包括堆

栈段、数据段和代码段等,这种分段结构的程序称为EXE程序。另有一种程序,其规模较小,而且只有一个用户使用,也无需与外部的其他模块进行装配,则可以把数据、代码连同堆栈段都包括在代码段内。这种程序称为COM程序。ASSUME只有一个数据项,即CS:CO

DE。由于DOS的装入程序在加载这种COM程序时,把4个段寄存器都初始化在PSP的起点上,所以把IP初始化在0100H,SP初始化在整个段的高端,如图3-2所示。把例3-1改写为COM程序的形式,则程序如下;co

desegmentassumecs:codestaprocfarorg0100hstart:jmpinitorg0200hbufferdw0,1,-5,10,256,-128,-100,45,6dw3,

-15,-67,39,4,20,-1668,-32766dw32765,-525,300countequ($-buffer)/2maxdw?Init:movax,csmovds,axleasi,buffermovcx,countdeccxmovax,[si]chkmax:addsi,2cmp

[si],axjlenextmovax,[si]next:loopchkmaxmovmax,axretstaendpcodeendsendsta伪指令ORG0100H通知汇编器,程序起始地址是0100H。这是因为前256个字节是DOS建立的PSP区,DO

S装入COM程序时总把IP定在0100H,所以在0100H处必须是可执行的指令代码。COM程序不允许定义堆栈段。所以汇编时会产生一个“没有堆栈段”的出错信息,对此可不必理会。只要没有其他错误,便可以连接产生EXE文件,并且可以使用DOS的EXE2B

IN实用程序把这个EXE文件转化为COM文件。与EXE程序相比,COM程序更紧凑,执行起来更快一些。但COM程序(数码、代码、堆栈合起来),不能超过64KH。第三节数据定义任何一个程序都要使用数据,本节讨论汇编语言的数据定义方法。一、常量、变量和标号汇编语言中数据项有常量、变量和标号三种类

型。1.常量一个常量用二进制表示时,该数据须用字母B结尾;用十进制表示常量时可用D结尾,也可以不用;用十六进制表示常量时要以字母H结尾,规定十六进制数第一个字符必须是数字,如:0F12BH,1234H;如果用八进制表示常量则以字母Q结尾或者

以字母O结尾。字符串必须用单引号或双引号括起来,汇编语言把它们汇编成相应的ASCII码。例如:字符串’AB‟被汇编为41H,42H;对字符串’12‟,则被汇编为31H,32H。2.变量变量实际上代表着内存单元,因此有时也称为内存变量。上例中的MAX

单元就是一个变量,它是16位的。既然变量是内存单元,它必然具有段地址和段内偏移量。所以变量有三个属性:段基址、段内偏移量以及类型。变量的类型是指变量具有的字节数。字节变量表示一个8位数据,其类型为1;字变量表示一个十六位数据其类型为2

;双字变量表示一个32位的数据,其类型为4。3.标号标号实际上是代码段中的某一指令的地址。它也有三个属性:段地址、段内偏移量和类型。标号的类型有两种:NEAR标号,它只能在定义它的段内被引用,其类型为-1(0FFFFH

),它代表一个程序地址的偏移量;FAR标号,它既可以在定义它的段内被引用,也可以在其他段内被引用,其类型为-2(0FFFEH),它代表了指令的段地址和偏移量。标号可以在各种转移指令中作为操作数使用。它只能定义在可执行的码段中。如果在定义标号时使用了冒

号(:),则汇编程序确定它是NEAR标号。远标号的定义见运算符PTR一节。常量和变量的名字及标号不能用宏汇编中的保留字。二、数据定义或分配数据单元的伪操作语句汇编语言提供两种定义数据或分配数据单元的语句格式。1.第

一种格式[名字]伪操作表达式其中名字域是可选的,但如果程序中要引用,则名字必须给出。伪操作域可以是DB、DW、DD。其意义为:DB—定义字节DW—定义字DD—定义双字表达式域可以是常数,也可以是表达式,还可以是一个问号。如果是问

号,表示该数据定义语句用于保留(或称分配)内存空间,但不对该空间初始化。否则不仅为数据分配了内存空间,而且还把该空间初始化为表达式所指定的值。例如:MAXDW?语句分配了一个字单元以备存放最大值(例3-1)。BUFFERDW0,1,-5语句分配了三个字单元,并初始化为0,1,-5,即00H,00

H,01H,00H,0FBH,0FFH。A0DB1,2+3,4×5使用了表达式。A1DD12345H语句分配一个双字单元,并初始化为:45H,23H,01H,00H。2.第二种格式[名字]伪操作DUP(表达式)

此格式可定义一些重复的数据或分配一数据块空间。例如:DATA1DW10DUP(?);分配十个字的空间。DATA2DB20DUP(5);分配20个字节,初始化为5。DB100DUP(‟STACK‟);分配50

0字节,并重复填入53H、54H、41H、43H、4BH。三、等值伪操作语句1.EQU语句使用EQU可以用一个名字来代表一个常数或者表达式,例如:COUNTEQU20;COUNT就等于20。BLOCKDB‟Readafterme!‟NUMEQU$-BLOCK后两句表示使NUM获得BLOCK

块的字节效,即字符串的长度。$表示汇编程序的汇编地址计数器的当前值。在这里$等于字符串中最后一个字符“!”所在单元的下一个字节的地址的偏移量,BLOCK是字符串第一个字符‘R‟所在的单元的偏移量,$-BLOCK就得到字符

串的长度。使用EQU应注意一点,使用EQU对某个名字赋值后,不能再用EQU伪操作对该名字重新赋值。另一点,名字后面不要加冒号(:)。2.等号伪操作语句(赋值语句)等号伪操作也可以把一个常数或表达式指定给一个名字。用等号

伪操作定义的名字可以重新定义。B1=6;B1定义为6B1=10;重定义B1为10B1EQU20;出错,因为B1已经定义,不能用EQU重新定义。第四节汇编语言的运算符一、算术运算符算术运算符有加(+)、减(-)、乘(×)、除(/)、模(MOD)、左移(SHL)和右移(SHR)七种。除

法返回的是商,而MOD操作返回除法操作的余数,例如:PI_INTEQU31416/10000;PI_INT=3PI_REMEQU31416MOD10000;N_REM=1416SHL和SHR是移位操作,一般在建立屏蔽字时使用。例如:MASKBEQU0011

0010BMASKB1EQUMASKBSHL2;MASKB1=11001000BMASKB2=MASKBSHR2;MASKB2=00001100B二、逻辑运算符汇编语言的逻辑运算符有:AND—逻辑与OR—逻辑或XOR—逻辑异

或NOT—逻辑非逻辑运算符与逻辑运算指令的区别在于,前者在汇编时完成逻辑运算,而后者在执行指令时完成逻辑运算。MASKBEQU00101011BMOVAL,5EHANDAL,MASKBAND0FH在汇编时汇编

程序计算出MASKBAND0FH为0BH,按ANDAL,0BH汇编第三条指令。当指令执行时AL才能得到0AH。三、关系运算符关系运算符有:EQ—等于NE—不等LT—小于GT—大于LE—小于等于GE—大于等于

关系运算符比较两个操作数并产生一个逻辑值。如果关系成立,则结果为真(0FFFFH);否则为假(0000H)。由于关系运算符只能产生两个值,因此很少单独使用。一般都同其他操作结合以构成一个判断表达式。例如要实现5如果CHOICE<20AX=6如果

CHOICE≥20那么可以使用下列语句:MOVAX,((CHOICELT20)AND5)OR((CHOICEGE20)AND6)四、值返回运算符1.$运算符返回汇编器当前地址计数器的值。在第三节中已经举过例子。2.S

EG和OFFSET运算符SEG和OFFSET运算符分别返回一个变量或标号的段地址和偏移地址。例如:MOVAX,SEGTABLE;把TABLE的段地址送AXMOVBX,OFFSETTABLE;把TABLE的偏移地址送BX第二条指令等价于LEABXTABLE指令。3.TYPE运算符TY

PE运算符用于返回变量和标号的类型。对于字节变量返回1,对于字变量返回2,对于双字变量返回4;对于NEAR标号返回值-1(0FFFFH),对于FAR标号返回值-2(0FFFEH)。例如,若AB是DB定义的变量,执行MOVAX,TYPEAB则AX=0001H。4.LENGTH和

SIZE运算符LENGTH和SIZE运算符只对用DUP定义的变量有意义。LENGTH返回的是分配给该变量的元素的个数,而SIZE返回的是分配给变量的字节数,或者说它返回的是变量的长度与其类型之积。例如:TABLEDW100DUP(?)执行指令MOVCX,LENGTHTABLE,则CX=1

00,若执行MOVCX,SIZETABLE则CX=100×2=200。5.HIGH和LOWHIGH和LOW运算符分别返回一个16位表达式的高位字节和低位字节,例如:NUMEQU0CDEFHMOVAH,HIGHNUM;AH=0CDHMOVAL,LOWNUM;A

L=0EFH五、属性运算符1.PTR运算符PTR运算符用于暂时改变变量或标号的原有属性。PTR的一般格式是:新属性PTR表达式例如F1是DW定义的字变量,F2是DB定义的字节变量,若要取F1的低字节,或者要将F

2开始的两个字节送BX,则可以:F1DW1234HF2DB23H,56H,18H…MOVAL,BYTEPTRF1;AL=34HMOVBX,WORDPTRF2;BX=5623H传送指令的源操作数和目的操作数的位数必须一致。当不一致时,可以用PTR运算符暂改变

一下变量的属性,使两个操作数的类型一致。PTR还常在段间调用指令中的使用:CALLDWORDPTR[BX];远程调用,把BX指向的四个单元内容作为远调用的目标地址。与PTR运算符具有类似功能的是LABEL伪操作指令。LABEL可以对巳定义的内存单元的属性重定义,并取一个新名字。

其格式为:名字LABEL类型例如:CFBLABELBYTE;CFB是字节变量,具有与DFW相同的地址。DFWDW4567H;DFW是字变量EFWLABELWORD;EFW是字变量。具有与FFB相同的地址FFBDB89H,40H;FFB是字节变量…MOVAL,CFB;AL=67HMOV

BX,EFW;BX=4089HMOVCX,DFW;CX=4567HMOVAH,FFB;AH=89H从上面可以看出LABEL可以使一个变量具有多种属性,(当然也有多个名字)。LABEL操作本身不分配内存单元。2.THIS运算符THIS运算符与PTR运算符有类似的功能,但

新的属性放在THIS的右边。例如:FIRSTEQUTHISBYTE;FIRST变量具有BYTE属性其地址与SECOND相同。SECONDDW5678HMOVAX,TYPEFIRST;AX=0001H,FIRST类型

是字节变量。MOVBL,FIRST;BL=78HTHIS可以用来定义FAR标号,例如:MILESEQUTHISFAR;MILES是远标号,其地址与下面的CMP指令相同CMPSUM,100…>64KJMPMILES;段间转移。3.段超越运算符段超越运算符由段寄存器和

冒号表示。例如ES:、CS:等。段超越运算符强迫当前指令的操作数的寻址不按约定的段进行,而由超越运算符指定的段寻址。如MOVAX,ES:[BX]强迫源操作数来自ES段,而不是DS段。4.SHORT运算符SHORT运算符通知汇编器,转移目标在+127~-128之间。例如JMPS

HORTF1JMP指令原为三字节指令,加SHORT后,汇编成两字节指令。程序编辑编译连接运行调试说明.MODELSMALLMDATASEGMENTPAGEM1DB06H,75H,?M2DB14H,27H,?M3DB34H,12H,?XDB11HYDW2233HS1DB“THISI

STHERESULT:”,,0AH,0DH,‟$‟S2DB“M2[2]=$”MDATAENDSMSTACKSEGMENTSTACKDW6DUP(?)TOPLABELWORDMSTACKENDSMCODESEGMENTASSUMECS:MCODE,DS:MDATA,

SS:MSTACKSTART:MOVAX,MDATAMOVDS,AXMOVAX,MSTACK;MOVSS,AXMOVBP,TOPMOVBP,OFFSETTOP;MOVSP,BPMOVBX,OFFSETM1MOVAL,[BX]MOVAH,[BX+1]CALLMP

ROCMOV[BX+2],ALMOVX,AL;MOVBX,OFFSETM2MOVAL,M2[0]MOVAH,M2[1]CALLMPROCMOVM2[2],ALMOVBX,OFFSETM3MOVAL,[BX]MOVAH,[BX+1]CALLMPROCMOV[

BX+2],ALMOVDX,OFFSETS1MOVAH,9;功能号9INT21H;DOS系统功能调用,显示字符串MOVDX,OFFSETS2MOVAH,9INT21HMOVDL,M2[2]MOVCL,4;先显示十位数SHRDL,CLORDL,30H;转成A

SCII码MOVAH,2;功能号2INT21H;DOS系统功能调用,显示单个字符MOVDL,M2[2]ANDDL,0FH;显示个位数ORDL,30HMOVAH,2INT21H;HLT;DOS系统功能MOVAH,4CH;功能号4CHINT21H;返回DOSMPROCPROCNEAR;过程PUSH

BXADDAL,AHDAAPOPBXRETMPROCENDPMCODEENDSENDSTART执行程序结果,屏幕显示:THISISTHERESULT:M2[2]=41例程:E1.ASM结合此程序对汇编程序MASM

.EXE、连接程序LINK.EXE和调试程序CV.EXE的使用进行介绍。在E1.ASM中首先定义数据段MDATA,其中定义M1、M2、M3字节数据变量,X字节变量,Y字变量,S1、S2字符串用于结果显示信息输出。堆栈段只开了6个空间,其中TOP可以不用,因为SP可不用初始化。代码

段中:①堆栈段和SP可不进行初始化。②代码段由主程序和过程(子程序)MPROC组成,可完成对两个装配型十进制数相加的运算,并可调用DOS系统功能(参加教材P101)将结果信息进行显示。③用两种方法访问数组变量。

④在程序执行CALL过程和RET指令以及PUSH、POP指令时结合CodeView对堆栈的变化进行观察。一、编辑程序:在MS-DOS方式下使用EDIT程序:>EDITE1.ASM回车也可使用其它文本编辑软件

,但程序要以一般文本方式保存,程序后缀名为.ASM。二、汇编程序:在MS-DOS方式下使用MASM.EXE程序:>MASM/HE回车显示命令选项信息>MASM/ZIE1.ASM;回车生成E1.OBJ文件/Z

I命令选项的功能是指示MASM在汇编时将符号和行号等信息加入到生成的目标文件中,这些信息在使用CV调试时要使用。后加分号(;)可使MASM只生成E1.OBJ文件。如果程序有语法等错误,汇编时将显示错误信息,并给出错误所在的行号,以便进行修改,如:SHRDL

,4显示:e1.asm(52):errorA2050:Improperoperandtype0WarningErrors1SevereErrors三、连接程序:在MS-DOS方式下使用LINK.EXE程序:>LINK/COE1;回车生

成E1.EXE/CO命令选项是指示LINK程序生成支持CodeView调试的可执行程序。分号(;)使得LINK只生成E1.EXE文件。如果没有错误LINK执行后显示如下信息:Microsoft(R)OverlayLinkerVersi

on3.64Copyright(C)MicrosoftCorp1983-1988.Allrightsreserved.四、调试程序:在MS-DOS方式下使用CodeView程序CV.EXE:>CVE1回车或>CVE1.EXE回车如果被调试

程序中没有CodeView所需要的调试符号、行号等信息,则显示:NoSymbolicInformation如果程序调试运行正确后,则应不加/ZI和/CO选项,再将程序编译连接生成最终产品E1.EXE,此时程序应比调试用的E1.EXE小。五、CodeView的使用简介1.CodeView

的窗口:①程序窗口②命令行窗口③寄存器窗口④观察窗口有菜单操作,也可利用快捷键,参见HELP帮助说明。2.快捷键:观察窗口程序窗口寄存器窗口命令行窗口F2-寄存器窗口显示;F3-源程序、汇编显示转换;F4-用户输出界面显示;F6-当前窗口转换;。3.?命令显示

表达式、变量值格式:?Expression[,format]format:d或i-有正负号的十进制整数u-无正负号的十进制整数o-无正负号的八进制整数X-十六进制整数(大写形式表示)x-十六进制整数(小写形式表示)f-带符号十进制浮点数,小数位数6位e-以

科学记号格式表示小数位数6位例如:显示程序数据段中的x变量。>?X回车>?x,d回车>?x-5,x回车>0x0011>17>000c4.X命令显示符号(变量)的地址例如:>X回车显示程序中所有符号(变量)的地址>X?m1回

车>x?S1回车显示指定符号的地址>X*显示所有模块名E1.OBJ5.DUMP命令显示内存数据,与SYMDEB中的D命令相似。例如:>DBm1回车>DAS1回车>DWY回车>DBDS:0000L20回车6.设置观察命令Watch用于打开观察窗口,实时观察变量、内存等。

例如:>WBm1L3>WBm2L3>WBx>WWy>WAS1L18>WAS2L8>WBDS:0000L10观察指定内存>WWSS:0000L8对堆栈区观察7.删除观察命令WatchDelete从窗口中删除由Watch命令设置的观察变量、内存等。例如:>Y1删除编号1

号观察量>Y*全部删除,关闭Watch窗口8.利用快捷键执行调试命令F8-程序单步跟踪,可随CALL过程指令进入子程序。F10-程序逐步执行,可将CALL指令一次执行完,不进入子程序。F7-程序执行到光标所在行,光标所在行应

在当前程序执行位置之后。F5-程序从当前位置执行到断点或执行到结束,即GO命令。F9-在光标所在位置设置或清楚断点,断点行高亮显示。用F8执行CALL、RET、PUSH、POP指令时注意观察堆栈变化。9.

其它命令内存修改命令:>EBDS:0000回车观察窗口中数据变化,操作同SYMDEB。反汇编命令:>A0000回车如可将程序第一个指令修改为MOVBX,4681。寄存器命令:>R或>RF同SYMDEB,RF可列出标位的所有代表符号,方便修改,而且

置位时为红色。修改基数命令:>N10设为十进制>N16设为十六进制CodeView开始默认为十六进制。.命令:>.可将程序当前执行所在行显示在屏幕中,特别是找不到程序当前位置时,可用此命令。CodeView调试程序的调试指令非常丰富,详细使用说明参阅软件本身HELP的内容

。第五节基本结构程序设计一、顺序结构程序的基本结构有四种:顺序结构、分支结构、循环结构以及子程序结构。本节将分别介绍这四种基本结构,并举例说明基本结构程序的设计方法。顺序结构是最基本的结构。其特点是语句按顺序逐步执行,无分支、循环和转移。例3-2两个32位无符号数乘法程序。在8

086指令系统中,数据是16位的且最长只有16位数的乘法指令。所以32位乘法需要做4次16位乘法,每次都要将部分积相加来实现,相加时则要注意位数对齐。我们用连续的四个字单元来存放乘积,各部分积应加到适当单元。程序如下:;exm3_2.asm32bitsmultiplyd

atasegmentnum1dw8000h,8000hnum2dw8008h,8000hmutdw4dup(0)dataendsstacksegmentstack‟stack‟db100dup(‟s‟)stackendscodesegme

ntpara„code‟assumecs:code,ds:data,ss:stackprocfarpushdsxorax,axpushaxmovax,datamovds,axleabx,num1movax,[bx];b→axmovsi,[bx+4];d→simovd

i,[bx+6];c→dimulsi;b*dmov[bx+8],ax;部分积1存于积单元中。mov[bx+10],dxmovax,[bx+2];a→axmulsi;a*dadd[bx+10],axadc[bx+12],dx;带进位加入积2单元中movax,[bx];b→axmuldi;b*cad

d[bx+10],ax;b*c加入积单元adc[bx+12],dx;带进位加至部分积3adcwordptr[bx+14],0;进位加至部分积4movax,[bx+2];a→axmuldi;a*cadd[bx+12],axa

dc[bx+14],dxretstaendpcodeendendsta二、分支结构始终是顺序结构的程序实际上并不多见,经常都会碰到有分支的情况。典型的分支结构如图3-3所示。分支结构程序通常采用条件转移指令或者转移表来实现。下面举例说明。YN1

当x>0例3-3符号函数y=0当x=0-1当x<0要实现符号函数,只要把x从内存中取出来,执行一次“与”或“或”操作,就可把x的数值特征反映在标志上,再根据标志来转移。程序框图如图3-4所示,程序如下:;exm3_3.asmsignfunctiondatasegmentxdw12yd

w?dataendsstacksegmentstack„stack‟db100dup(„s‟)stackendscodesegmentpara„code‟assumecs:code,ds:data,ss:stacksignprocfarpushdsx

orax,axpushaxmovax,datamovds,axmovax,xandax,ax;建立标志jzzerojnsplusmovbx,0ffffhjmpdonezero:movbx,0jmpdoneplus:movbx,1done:movy,bxretsigne

ndpcodeendsendsign例3-4根据BUFFER单元的值,转到相应的子程序。子程序的入口地址存放在转移表BRTAB中。若BUFFER内容等于n,则转到第n个子程序(n从1~256,0代表256)。这是一种大散转,散转形式如图3-5所示。程序

如下:;exam3_4.asmbranchinguponaldatasegmentbufferdb3brtabdw0000h,3000hdw0100h,3050hdw0000h,3090hdw0100h,4050hdw0000h,6000hdataendsstacksegmentstack„sta

ck‟db100dup(„s‟)stackendscodesegmentpara„code‟assumecs:code,ds:data,ss:stackbrchprocfarpushdsxorax,axpushaxmovax,datamovds,axleabx,brtabmoval,buffe

rdecalmovah,0shlax,1;AL*2shlax,1;AL*4addbx,axjmpdwordptr[bx]retbrchendpcodeendsendbrch三、循环结构循环结构是程序设计中最常用的结构。典型的循环结构如图3-6

所示。循环结构由以下几部分组成。1.初始化部分:用于对循环过程中的工作单元及寄存器置初始值。例如设置地址指针、寄存器清零、设置标志等。2.处理部分:重复进行的数据处理工作。3.循环控制部分:为下一轮处理修正地址指针和计数器值等,并判断结束条件是否满足。满足则退出循

环。4.结束部分:分析和存放结果由图(a)的处理部分至少要做一次。图(b)处理部分和控制部分交换了一下,处理部分可不执行,允许0次循环,因而更有效。图3-6(a)结构程序如cyclel.asm所示:;cycle1.asm;unclude0cyclemovax,3

000hmovds,axmovsi,0100hmovdi,0200hmovcx,100l1:moval,[si]mov[di],aladdsi,1adddi,1loopl1int20h图3-6(b)结构程序如cycle2.asm所示:;cycle

2.asm;include0cyclemovax,3000hmovds,axmovsi,0100hmovdi,0200hmovcx,100inccxl1:deccxjzl2moval,[si]mov[di],alincsiincdijmpl1l2:int20h图3-6(b)结构程序;cycl

e3.asm;include0cyclemovax,3000hmovds,axmovsi,0100hmovdi,0200hmovcx,100decsidecdiinccxl1:incsiincdideccxjzl2moval,[si]mov[di],aljmpl1l2:int20h很多情

况用计数器控制循环次数,前面举的例子大多数属这种情况。但有的问题事先不知道需要重复的次数,而要按问题的条件控制循环。例如用牛顿迭代法求解,事先我们不知道要迭代多少次,而是根据相邻两次所求得值的误差小于一定值时才停止迭代,即停止循环。例3-5求一个16位无符号

数的整数平方根,选用牛顿迭代法来解算。程序中常常是一个循环包含另一个循环,称为多重循环。如延时程序就经常用多重循环。例如,已知10ms的延时程序为:MOVCX,2801WAT:LOOPWAT若要延时100ms,可将上述循环再执行10次:MOV

BL,10DELY:MOVCX,2801WAT:LOOPWATDECBLJNZDELY下面举一个双重循环的例子。例3-6气泡排序法。设有10个符号数,要求将这10个数由小到大排列。解决这个问题的算法及步骤如下:(1)设定

初值:BL=0(交换标志置0)SI指向最后一个元素CONT=元素个数-l=比较次数(2)比较最后一个数和最后第二个数,若最后一个数大,则转第3步,否则将它们交换位置,并将BL置-1,CONT减1。(3)CONT减至0否,若CONT≠0,则重复第2

步。这一轮比较完则进入第4步。(4)检查交换标志,若BL=0,则结束排序;若BL≠0则转第1步,进行下一轮比较。气泡排序的扫描过程如表3-3所示。程序流程图如图3-8所示。程序如下:;exm3_6.a

smbubblesortdatasegmentbufferdw1,30,-60,125,90,-1890,67,-3844,9,50contequ$-buffdataendsstacksegmentstack„stack‟db100

dup(„s‟)stackendscodesegmentpara„code‟assumecs:code,ds:data,ss:stacksortprocfarpushdsxorax,axpushaxmovax,datamovd

s,axmoves,axcoti:movbl,0;setflag=0movcx,contmovsi,cxdecsidecsi;si->bottomofarrayshrcx,1;cx:elementnumdeccxagan:movax,buff[si]cmpax

,buff[si-2]jgenextxchgax,buff[si-2]movbuff[si],axmovbl,-1next:decsidecsiloopagancmpbl,0jnecotiretsortendpcodeendsendsort四、子程序结构若一段指令在一个程序中多处使用,或在多个

程序中用到,则通常把这段指令当作一个独立的模块处理,称为子程序(8088称为过程)。主、子程序关系在许多情况下,希望子程序有通用性,希望子程序除有使用说明外,还能接受主程序传来的入口参数,在子程序执行完后把出口参数传递

给主程序。例如两个多字节数相加的子程序,调用时允许主程序给出两个加数(或它们的地址),即入口参数;子程序返回时应能返回“和”或者“和”的地址,这个“和”或“和”的地址便是出口参数。参数的传递通常有三种方式:(1)用寄存器传递,适用于参数个数少的情况。(2)用程序存储器中的参数表传递,这个参数表

紧跟在调用指令的后面。(3)利用堆栈传递参数,适用于参数较多且子程序有嵌套、递归调用的情况。(一)用程序存储器中的参数表传递参数在主程序中把要传送的参数直接放在调用指令的后面。例如:CALLADDSUBNUM1DD12345678H;定

义被加数NUM2DD5678H;定义加数BUFFERDD?;保留“和”的存放单元在子程序中,到堆栈中去取返回地址(CALL指令执行时压入堆栈的NUM1的地址,若是NEAR型调用,即是NUM1的偏移地址),进而获得参数。应该注意的是,从子程序返回时应该修

改返回地址,跨过参数,返回到真正的指令地址。子程序中相应指令如下:PUSHBPMOVBP,SP…MOVBX,[BP+2];从堆栈中取出返回的偏移(近调)MOVCX,CS:[BX];地址,即参数所在地取参数MOVSI,CS:[BX+2]…ADDBX,12

;修改返回地址,使子程序返回MOV[BP+2],BX;到参数后面的指令…RET如果传送的是变量(即参数的地址)不是参数的数值,则传送的参数是参数的地址。这时在主程序中CALL指令后面用的是:NUM1DWOFFSETV

AL1,SEGVAL1类型的语句,在子程序中要用LDSSI,DWORDPTRCS:[BX]类型的语句取参数的地址。例3-764位二进制数相加(不考虑进位、即和不超过64位),采用在CALL指令后定义加数及和

的偏移地址和段地址的参数传递方法。程序如下:;exm3_7.asm64bitsadditiondatasegmentval1dd10h,12345678hval2dd20h,34567890hbuffer

dd?,?dataendsstacksegmentstack„stack‟db100dup(„s‟)stackendscodesegmentpara„code‟assumecs:code,ds:data,ss:stackprocfarpushdsxorax,axpushaxmov

ax,datamovds,axmoves,axcalladd64num1dwoffsetval1,segval1num2dwoffsetval2,segval2resultdwoffsetbuffer,segbufferretstaendpadd64procp

ushbpmovbp,sppushfpushaxpushcxpushbxpushsipushdimovbx,[bp+2];getretaddressldssi,dwordptrcs:[bx];getoprandaddressldsdx,dwordptrc

s:[bx+4]lesdi,dwordptrcs:[bx+8]xchgdx,bxmovcx,4clcagain:lodswadcax,[bx]stoswincbxincbxloopagainmovbx,[bp+2]addbx,0ch;adjustretaddressmov[bp+2],bxp

opdipopsipopbxpopcxpopaxpopfpopbpretadd64endpcodeendsendsta例3-7在码段和堆栈段情况如图3-10所示。(二)用堆栈传递参数堆栈传递适用于参数较多且子程序有嵌套、递归调用

的情况。在主程序中把参数压入堆栈后调用子程序,子程序中将参数从堆栈中弹出。例3-8数组求和子程序。假设有一数组求和子程序SUM,试用这个子程序分别求出ARY1和ARY2两个数组的和,结果分别存入SUM1和SUM2字单元中。SUM子程序的说明见程序中注释部分。第一次调用子程序后堆栈

的情况如图3-11所示。程序如下:;exm3_8.asmdataarraysummationdatasegmentaryldb03h,07h,50h,06h,23h,45h,0f6h,0dfhlen1eq

u$-ary1sum1dw?ary2db33h,44h,55h,12h,78h,89h,0feh,0cdhlen2equ$-ary2sum2dw?dataendsstacksegmentstack„stack‟db100dup(‟s‟)stackendscodesegme

ntpara„code‟assumecs:codc,ds:data,ss:stackstaprocfarpushdsxorax,axpushaxmovax,datamovds,axmovax,len1pushaxleaax,ary1pushaxcallsummovax,len2

pushaxleaax,ary2pushaxcallsumretstaendpsumprocpushbpmovbp,sppushaxpushbxpushcxpushfmovcx,[bp+6];getarra

ylenthmovbx,[bp+4];getoffsetaddressxorax,ax;sum=0add1:addal,[bx]adcah,0incbxloopadd1mov[bx],axpopfpopcxpopbxpopaxpop

bpret4sumendpcodeendsendsta第一次调子程序后堆栈的情况(三)子程序的递归调用例例3-9确定变量NUMB的阶乘,把结果存入变量FNUMB。变量NUMB的值大于0且小于8。按照阶乘的定义:这是一个递归定义(一个子程序调用它自己称为递归调用),所以在程序中

包含着子程序的递归调用。程序如下:;exm3_9.asmevaluaten!datasegmentnumdb3njdw?dataendsstacksegmentstack„stack‟db200dup(‟s‟)stackendscodesegmentpara„code‟assume

cs:code,ds:data,ss:stackstaprocfarpushdsxorax,axpushaxmovax,datamovds,axpushcxmovah,0mova1,numcallfactorx1:movnj,axpopcxretsta

endpfactorprocpushaxsubax,1jnefconpopaxjmpretunfcon:callfactorx2:popcxmulclRetun:retfactorendpcodeend

sendsta第六节操作系统资源的使用对数据的输入输出,大多数现代计算机都有两种资源可供使用:一种是与硬件相关的基本输入输出系统;另一种是与硬件无关的基本输入输出系统即由操作系统提供的输入输出功能,常称DOS功能调用。属于第一种的有由ROMBIOS(

BASICI/OSYSTEM)的INT16H提供的三种键盘输入输出,由INT10H提供的16种功能支持屏幕处理等等。第二种是操作系统为用户提供的使用输入输出设备的系统资源,也是提倡采用的一种资源。它不仅使用简单,而且可以确保所开发的软件在同一操作系统下的(不同计

算机)兼容性。在多用户和多任务的环境下,与硬件有关的ROMBIOS资源只允许操作系统这个特殊用户使用,用户只可以使用INT21H提供的功能调用。INT21H功能调用包括字符输入、字符输出、磁盘控制、文件管理、记录操作、目录操作、动态存储分配

、网络功能等。每次调用前需把功能号送入AH寄存器中,并在有关的寄存器中设置入口参数,再使用INT21H指令。下面举例说明调用的方法。(1)DOS的2号功能调用,显示单个字符调用格式:MOVDL,‘字符’MOVAH,02HINT

21H功能:显示DL寄存器的字符(ASCII码表示)。入口:DL中存放要显示的字符或命令的ASCH码。出口:无例3-10在CRT上连续显示0~9数字100遍后返回DOS。(2)DOS的9号功能调用,字符串显示调用格式:MOVDX,OFFSETST

RING;DS:DX指向以$为结束的字符串首址MOVAH,09HINT21H功能:在屏幕上输出内存中以‘$’符结束的字符串(以ASCII码表示的)。入口:DS:DX指向字符串首地址。出口:无例3-11在CRT上连续显示00~59,同时在CRT上显示两个以上

的字符。(3)DOS的10号(0AH)功能调用,字符串输入调用格式:MOVDX,OFFSETBUFFERMOVAH,0AHINT21H功能:从键盘输入字符到内存缓冲区,以回车键为结束。入口:DS:DX指向内存缓冲区,缓冲区第一字节由用户设置最大输入字符数(1~

255)含回车结束码。出口:缓冲区第二字节是实际输入的字符数(回车符除外),从第三字节开始到回车符止是输入缓冲区的字符(ASCII码)。注意,如果输入的字符数超过最大设定值,则后输入的字符被忽略,且铃响

。若输入的字符数少于设定值,则缓冲区余下部分维持原内容,若键入Ctrl+Break或Ctrl+C,则退出。在数据段应这样写:datasegmentpara„data‟bufferdb10;定义最大输入字符数,含回车符db?;保留

一个字节返回实际输入字符数db10dup(?);开辟最大字符数的空间dataends例3-12软件时钟程序(4)DOS的1号功能调用,键盘输入单字符使用格式:MOVAH,1INT21H它没有入口参数,执行1号系统功能调用时,系统等待键盘输入,待程序员按下任何键,系统

先检查是否Ctrl-Break键,如果是则退出,否则将键入字符的ASCII码置入AL寄存器中,并在屏幕上显示该字符。(5)DOS的8号功能调用,无回显键盘输入单字符等待从键盘输入单字符,将其ASCII码置入AL寄存器中。

但不送屏幕显示,其使用格式如下:MOVAH,8INT21H它没有入口参数,与1号系统功能调用的区别仅在于键入的字符不送屏幕显示。(6)DOS的3号功能调用,从串口输入单字符其使用格式如下:MOVAH,3INT21H它没有入口参数,系统将从异步通信口串行输入的字符置入A

L寄存器中。(7)DOS的4号功能调用,向串口输出单字符使用格式如下:MOVDL,‘$‟MOVAH,4INT21H执行结果将DL寄存器中的字符通过异步通信口串行输出。(8)DOS的4CH号功能调用,返回操作系统使用格式如下:MOVAH,4CHINT21H它没有

入口参数,执行结果是结束当前正在执行的程序并返回操作系统。屏幕显示操作系统提示符(N>),N为当前使用的驱动器名。(9)DOS的2BH号功能调用,设置日期其功能是设置有效日期。将年号置入CX寄存器中,月号置如DH寄存器中,日期置入DL寄存器中。MOVC

X,1990MOVCX,07D0H;2000年MOVDH,12MOVDH,0BH;11月MOVDL,26MOVDL,15H;21日MOVAH,2BHMOVAH,2BHINT21HINT21H如果设置成功0→AL

寄存器,否则FFH→AL寄存器。(10)DOS的2AH号功能调用,取得日期其功能是将当前有效日期取到CX和DX寄存器中,存放格式与设置日期时相同,其使用格式如下所示:MOVAH,2AHINT21H它没有入口参数,执行结果是将年号置入CX寄存器中,月份和日期置入DX寄存器中。注

意:显示时要变为十进制数和ASCII码。(11)DOS的2DH号功能调用,设置时间其功能是设置有效时间。例如当前有效时间是8点15分20.5秒,那么应将小时数8置入CH寄存器中、分钟数15置入CL寄存器中,秒数20置入

DH寄存器中,百分之一秒数50置入DL寄存器中。其使用格式如下所示:MOVCH,8MOVCL,15MOVDH,20MOVDL,50MOVAH,2DHINT21H如设置成功,AL寄存器清“0”,否则将AL寄存器置全“1”。(12)DOS的2CH号功能调用,

取得时间其功能是将当前时间置入CX和DX寄存器中,存放格式与设置时间相同。其使用格式如下所示:MOVAH,2CHINT21H它没有入口参数,执行结果是将当前时间送入CX和DX寄存器中供使用。注意:显示时要变为

十进制数和ASCII码。(13)磁盘文件管理DOS功能调用功能号3CH、3DH、3EH、40H。见书P110~112大作业系统功能调用编程练习目的:练习系统功能调用(屏幕清屏、光标坐标、字符字串显示、键盘读取)和过程调用与宏指令。实现功能:①清屏②显示年月日时:分:秒提示按某键

开始计时:00:00:01③提示按某键退出程序提示:清屏:MOVAX,0600HMOVBX,0754HMOVCX,0000HMOVDX,194FHINT10H设光标坐标:MOVAX,0200HMOVBX,0000HMOVCX,0000HMOVDX,0416H;第4行和第16列INT

10HINT16H为关于键盘的BIOS调用,可实现键盘状态的检测:MOVAH,1INT16H中断功能为:读如一个字符(不等待),参见P237读键盘状态,若无键按下ZF=1;若有键按下,ZF=0。AH中存放键盘扫描码,AL中存放ASCII字符。该中断只检测键盘

的状态,并不等待键盘的输入,加到程序中不会引起程序为等待键盘的输入而停止执行后续指令。第七节宏汇编与条件汇编一、宏定义、宏调用与宏扩展与前面子程序的设计方法不同。当一段程序要多次使用时,也可以用宏指令和宏汇编来实现。

宏汇编语言提供宏定义功能以定义一个宏指令。一个宏指令是一系列汇编指令的集合。宏指令一经定义,便可以在程序中使用。宏定义由宏定义伪操作MACRO和ENDM作为起始和结束的标志。例如:SHIFTMACROMOVCL,4SALAL

,CLENDMSHIFT是这个宏定义的名,也可以把它叫做一条宏指令,它代表AL中的内容左移4位。宏定义体在下面的程序中可用SHIFT来代替宏定义体中的全部语句。这个过程叫宏调用。当汇编程序(MASM.EXE)遇到宏指令时,它会把这条宏指令替换成宏定义体,这个过程叫宏扩展

。在定义宏时一定要注意宏定义必须出现在程序的开头,即堆栈段、数据段、代码段之前。宏定义还具有接收参量的能力。上面定义的SHIFT宏指令是固定对AL左移4位,如果要对不同的寄存器左移不同的次数,则可定义:SH

IFT1MACROx,yMOVCL,xSALy,CLENDM若要将BX寄存器内容左移二位则可用宏指令:SHIFT12,BX这里2和BX是实在参数。用形式参数x代表次数,y代表寄存器名。形式参数不仅可以出现在操作数部位,也可以出现在操作码部位。例如:SHIFT2M

ACROx,y,zMOVCL,xS&zy,CLENDM宏汇编中规定,若在宏定义体中的形式参数没有适当的分隔符,则不被看作形式参数,调用时也不被实在参数所代替。例如上例中的操作码部分是Sz,z与S之间没有分隔,则此处的z就不被看

作形式参数。要把它定义为形式参数,就必须在前面加上符号&。于是S&z中的z就被看作形式参量。若有宏调用:SHIFT28,SI,HR在汇编时会产生以下指令的目标代码:MOVCL,8SHRSI,CL其中参数z代替操作码中的一部分。二、LOCAL伪操作一个宏定义名可以用伪指令PURGE来取消,其格

式为:PURGE宏定义名[,…]有些宏定义中需要定义变量或标号。如果在同一个程序中多次使用相应的宏指令,则汇编程序会把它扩展成多个同样的宏扩展,这样就产生多个相同的变量名或标号名,这就违反了汇编程序对名字不能重复定义的规定。为此汇编语言提供LOCAL伪操作用于保证生成名字的唯一性。LOCAL伪操作

的一般格式是:LOCAL形式变量l,形式变量2,……形式变量是宏定义中使用的变量或标号。LOCAL伪操作使汇编程序把这些变量或标号当作形式变量,而在宏扩展时把它们变成实际变量。这些实际变量由两个问号(??)打头,后面是数字序列,如??0

000,??0001,??0002,……避免了名字的重复。LOCAL伪操作只能用在宏定义体内,而且必须是MACRO伪操后的第一个语句。例如要定义一个宏,使AL中的一位16进制数转换为ASCII码,则可以定义如下:CHA

NGEMACROLOCALP1CMPAL,10;如AL=0BH>0AHJLP1;如AL<A,则直接加30HADDAL,‘A‟-‘0‟-10;0BH+(41H-30H-10)P1:ADDAL,‘0‟;0BH+

7+30H=42HENDM=‘B‟若在程序两次调用CHANGE这个宏指令,则在宏汇编展开时为:…+CMPAL,10+JL??0000+ADDAL,‘A‟-‘0‟-10+??0000:ADDAL,‘0‟……+CMPAL,10+JL??0001+ADDAL,‘A‟-‘0‟-10+??0001

:ADDAL,‘0‟…三、重复伪操作1.REPT其格式为REPT<表达式>…}指令体ENDM这个伪指令可以重复执行指令体中所包含的语句,重复次数由表达式的值决定。例如:x=0REPT10x=x+1DBxENDM它把1~10分配给十个连续的存储单元。利用这个伪指令可以对某个存储区赋值(建立一个表)。

例:把数字0~9的ASCII码填入表TABLE中。CHAR=‘0‟TABLELABELBYTEREPT10DBCHARCHAR=CHAR+1ENDM2.IRP其格式为IRP形式参量<参数表>…}指令体ENDM此伪指令能重复执行指令体中所包含的语句,重复的次数由参数表中

参数的个数所决定,参数表中的参数必须用两个三角括号括起来,参数间用逗号分隔。每重复一次按次用参数表中的参数代替形式参量。例如:IRPx<1,2,3,4,5,6,7,8,9,10>DBxENDM就是把1到10分配给10个连续的存储单元。3.IRPC其格式为:IRPC形式参量,字符串…}指令体ENDM

此伪指令也能重复指令体部分的语句。重复执行的次数,取决于字符串中字符的个数。而且每次重复执行时,依次把字符串中的字符代替形式参量。例如:IRPCx,0123456789DBx+1ENDM其功能也是把1到10分配给10个连续的存储单元。四

、条件汇编汇编语言提供许多条件伪操作,以支持条件汇编功能。条件伪操作的一船格式如下:IF××;条件…[ELSE];可选的…ENDIF即如果条件为真,则汇编程序汇编直到ELSE以前的条件块,要是无ELSE,则汇编直到ENDIF之前的条件块

;如果条件为假,则汇编程序汇编ELSE后面的条件块,要是无ELSE,则不生成条件块。表3-4给出了汇编语言的条件伪操作及其意义。例3-1464位加法。定义一个宏ADD64,N1,N2,SUM分别为被加数、加数以及和的存放单元。调用此宏指令进行64位加法。程序如下:;exm3_4.asm64b

itsadditionmacrocallinitmacrocnam,snam,dnamassumecs:cnam,ss:snam,ds:dnampushdsxorax,axpushaxmovax,dnammovds,axendmadd64macron1,n2,buflocalne

xtleabx,n1movcx,4clcnext:movax,[bx]adcax,[bx+8]mov[bx+10h],axincbxincbxloopnextendmdatasegmentnum1ddl,123

456789num2dd2,45678hbuf1dd?,?num3dd3,345678hnum4dd4,456789hbuf2dd?,?dataendsstacksegmentstack„stack‟db100dup(„s‟)stackendscodesegment

para„code‟staprocfarinitcode,stack,dataadd64num1,num2,buf1add64num3,num4,buf2retstaendpcodeendsendsta第八节外部引用与全局说明一、EXTRN和PUBLIC伪操作前

面只讨论了单个模块的设计。实际的软件开发比较复杂,因此常把问题划分为若干个子任务,即模块。先对每个模块分别编制、调试,然后把各模块连接起来。模块程序设计中一个重要的问题是各个模块之间的通讯。模块间的通讯有多种方法,在此仅介绍一种最基本的也是最常用的方法。为了解决模块

间的过程调用和变量引用,汇编程序提供两个属性伪操作:外部名引用EXTRN和全局变量说明PUBLIC。EXTRN的格式为:EXTRN名字:类型[,…]用EXTRN伪操作说明的名字称为外部名,它指示在本模块中使用该名字,但这名字的定义是在要连

接的其他模块中进行的。这个名字可以是过程名,也可以是变量名。类型则是指名字的类型。一般放在模块的最前面。用EXTRN说明的外部名必须在另一个模块中用PUBLIC伪操作定义为全局的变量名或过程名。PUBLIC伪操作的格式如下:PUBLIC名字[,…]在一个模块中只有用PUBUC伪操作说明的名字

才能够被其他模块作为外部名加以引用。该名字必须在本模块中有定义。PUBLIC语句可以在模块中任何一行出现。二、外部过程的调用一个模块调用另一个单独汇编的模块中的过程称为对外部过程的调用。为了实现外部过程调用,应

当在主模块的外面用EXTRN说明被调用的外部名和类型,而被调用的子模块中用PUBLIC说明相应的名字为全局过程名。主模块和子模块的结构如下:;MAIN_PROGM.ASMEXTRNSUB_PROG:FARCODESEGMENTMAIN_PROGPROCFAR…

CALLSUB_PROG…RETMAIN_PROGENDPCODEENDSENDMAIN_PROG;SP.ASMSUB_PROGCODESEGMENTPUBLICSUB_PROGSUB_PROGPROCFAR…RETSUB_PROGENDPCODEENDSEND三、

外部数据变量的引用通常主模块中可以把一些变量用PUBLIC说明为全局变量,供子模块使用;而子模块中应用EXTRN说明它引用的外部变量名和类型。下面用例子说明外部过程的调用和外部变量的引用。例3-15多字节加法并显示结果(假

设和的字节数不增)。主模块调用三个子过程,其中回车换行CYLH子过程是近过程,位于主模块之中。另外两个过程多字节加法EXM3_15B和多字节显示EXM3_l5A是独立的两个模块,因而是外部调用。程序如下:;exm3_15.asm;mutl

ibytesadditionanddisplay;extraproccall,mainprompublicd1,d2,n1;全局变量定义extrnexm3_15a:far;外部过程说明extrnexm3_15b:fardatsegmentpara„dat‟d1db9

8h,35h,54h,78h,12h,34hn1=$-d1d2db12h,34h,56h,78h,90h,0datendsstacsegmentpara„stack‟sta1dw100dup(?)stacendscodesegmentpara„code‟assumecs:c

ode,ds:datassumees:dat,ss:stacstaprocfarpushdsxorax,axpushaxmovax,datmovds,axmoves,axleasi,d1addsi,n

l-1movcx,n1callexm3_15a;显示被callcylh加数leasi,d2addsi,n1-1movcx,n1callexm3_15a;显示加数callcylhcallexm3_15b;做加法leasi,d1addsi,

n1-1movcx,n1callexm3_15a;显示和retstaendpcylhprocmovd1,0dhmovah,2int21hmovd1,0ahmovah,2int21hretcylhendpcod

eendsendsta;exm3_15a.asm;multihexstoASCIIanddisplaypublicexm3_15acodesegmentpara„code‟assumecs:codeexm3_15aprocfarpushaxpushdxstdl1:lodsbcallchng;显示

AL中的16进制数字movd1,„‟movah,2int21h;显示空格loopl1popdxpopaxretexm3_15aendpchngprocpushbxpushcxmovbl,almovc1,4shra1,cl;转换并显示callhexasc;高半字节mov

a1,blanda1,0fh;转换并显示callhexasc;低半字节popcxpopbxretendphexascproc;AL中的0XHpushax转换为ASCII码pushdx并显示cmpa1,10jbl2adda1,7l2:a

ddal,30hmovd1,a1moval,2int21hpopdxpopaxrethexascendpcodeendsend;exm3_15b.asm;multbytesadditionsub_modulapublicexm3_15bextrnd1:byte,d2:bytee

xtrnn1:abscodesegmentpara„code‟assumecs:codeexm3_15bprocfarpushaxpushcxpushsipushdilessi,d1leadi,d2movcx,n1clcll1:moval,[di]adc[si],al

incdiincsiloopll1popdipopsipopcxpopaxretexm3_15bendpcodeendsend三个模块分别汇编产生各自的目标文件,然后连接LINKexm3_15exm3_15aexm3_15b得到exm3_15.exe文件。

小橙橙
小橙橙
文档分享,欢迎浏览!
  • 文档 25747
  • 被下载 7
  • 被收藏 0
相关资源
广告代码123
若发现您的权益受到侵害,请立即联系客服,我们会尽快为您处理。侵权客服QQ:395972555 (支持时间:9:00-21:00) 公众号
Powered by 太赞文库
×
确认删除?