第3章汇编语言程序设计课件_第1页
第3章汇编语言程序设计课件_第2页
第3章汇编语言程序设计课件_第3页
第3章汇编语言程序设计课件_第4页
第3章汇编语言程序设计课件_第5页
已阅读5页,还剩180页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第3章

汇编语言程序设计

3.1概述指令:计算机完成某种操作的命令程序:完成某种功能的指令序列软件:各种程序总称机器代码,汇编语言程序,汇编程序汇编语言程序建立步骤:(1)用编辑程序建立.ASM源文件(2)用LINK程序把.ASM文件转换为OBJ文件(3)用LINK程序把.OBJ文件转换为.EXE文件,或用EXE2BIN程序把.EXE文件转换为.COM文件(4)在DOS下直接键入.EXE文件或.COM文件的文件名就可运行该程序3.2

语句格式

语句格式:[名字]操作符操作数1,操作数2;[注释]

1.名字一种符号地址组成:A~Z,a~z,0~9,专用符号?、.、@、_、$限制:①第一个字符不能为数字②“.”必须为第一个字符③前31个字符有效④不能为关键字类型:标号:指令符号地址变量:数据符号地址2.操作符组成:CPU指令,伪指令,宏指令3.操作数指定参与操作的数据,或数据所在单元地址4.注释说明程序、指令功能,增加程序可读性3.3伪指令功能:指示汇编程序完成规定的操作,如选择处理器,定义数据,分配存储器等。一、程序开始与结束1.程序开始:可以用name,title给程序起名。格式:NAMEmodule_name汇编程序以模块名作为模块的名字,若未使用NAME,则可用TITLE给程序指定标题格式:TITLEtext文本在每一页上打印出来,若没有NAME,则text的前6个字符为模块名,text最多为60个字符。若未使用NAME、TITLE,则源文件名为模块名。2.程序结束:表示原程序结束,不可缺,源程序的最后一条语句。格式:END[label]标号指示程序开始执行的起始地址,多个模块连接,主程序用标号,其他程序不用,主程序缺省值为代码段第一条指令。3.MASM6.0定义的入口点、出口点入口点:.STARUP;产生设置DS、SS、SP代码,此时,END不用标号。出口点:

.EXIT;返回操作系统,常用值为0。例:.STARUP….EXIT0END二、处理器选择

功能:选择对应的指令集,也即对应的汇编执行语句集放在程序最前面缺省值为.8086此类指令主要有:.8086选择8086指令系统.286选择80286指令系统.286P选择保护方式下80286指令系统.386选择80386指令系统.386P选择保护方式下80386指令系统.486选择80486指令系统.486P选择保护方式下80486指令系统.586选择Pentium指令系统.586P选择保护方式下Pentium指令系统吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十讲三、段定义

段定义:确定代码组织与数据存储的方式

2种:完整的段定义和简化的段定义(MASM5.0以上)完整的段定义包括:(1)segment和end段定义(2)ASSUME段分配(3)GROUP段组定义

segment和end段定义(1)格式:

段名segment[定位类型][组合类型][字长类型][‘类别’]……段名end功能:定义段名、段属性。一般情况下,选项可以不用,用默认值,但若需连接本程序和其他程序,就要使用这些说明。段名是段的标识符,指明段的基址,由程序员指定。segment和end段定义(2)①定位类型定位类型:指定段起始边界,5种BYTE:

任意位置WORD:

偶地址,地址低1位为0DWORD:4的倍数地址,地址低2位为0PARA:16的倍数地址,地址低4位为0PAGE:256的倍数地址,地址低8位为0,一页的起点,默认值。segment和end段定义(3)②组合类型组合类型:表示本段与其它段之间,具有相同段名的各段的组合关系,为连接程序提供信息,属于连接类型,6种。PUBLIC:本段连接时将与有相同段名.public类型的其它段连接在一起,连接次序由连接命令指定(共用一个段),即同名段连接在一起,有共同段地址。STACK:用于说明堆栈段,把不同程序段中的具有SARCK类型的同名段组合而形成一个堆栈段,其长度为各原有段的总和,LINK自动将新段的段地址送SS,长度送SP,若未定义SARCK类型,需在程序中用指令设置SS、SP。COMMON:本段连接时,使具有COMMON类型的同名段具有同一个起始地址,所以会产生覆盖,新段的长度是最长COMMON段的长度,新段的内容取决于依次覆盖的最后内容。MEMORY:表示该段应定位在所有段的最下面(即地址最大的区域),如果模块中不止一个MEMORY段,以第一个遇到的作为MEMORY段,其它段作为COMMON段处理,而LINK程序在处理MEMORY时与PUBLIC同样对待。PRIVATE:独立段,与其它段逻辑上没有关系,不与同名段合并,默认值。AT表达式:指定本段起始地址为“表达式”,偏移量为0,不能用于代码段。segment和end段定义(4)③字长类型字长类型:386以后,说明使用16位寻址方式,还是32位寻址方式。.USE16:16位寻址方式,段长≤64KB,16位段地址,16位偏移量,默认值。.USE32:32位寻址方式,段长≤4GB,16位段地址,32位偏移量。④类别类别:引号括起的字符串,连接时,’类别’相同的分段(他们可能不同名)均放在连续的存储空间中,但他们仍然是不同的分段(连续空间)。ASSUME段分配

格式:ASSUME段寄存器名:段名,……功能:指定分段寄存器,说明哪个段使用哪个段寄存器。说明:①程序段必须用CS,堆栈段必须用SS②该语句一般放在代码段的最前面③说明性语句,除CS外(初始化赋值),各段寄存器在程序中赋值。④取消语句:ASSUMENOTHING一般汇编格式举例

DATA1SEGMENT‘DATA’…DATA1ENDSDATA2SEGMENT‘EXTRA’…DATA2ENDSDATA3SEGMENT‘DATA’…DATA3ENDSCODESEGMENT‘CODE’ASSUMECS:CODE,DS:DATA1,ES:DATA3,SS:DATA2START:MOVAX,DATA1MOVDS,AX;数据段地址赋给DSMOVAX,DATA2MOVSS,AX;堆栈段地址赋给SSMOVAX,DATA3MOVES,AX;附加段地址赋给ES…MOVAH,4CHINT21H;返回DOSCODEENDSENDSTARTGROUP段组定义

格式:段组名GROUP段名[,段名]功能:将指定的所有段分配在同一个物理存储器内,使用同一个组名,使用同一个DS内容。用户自行指定段组中的段,段组不影响各段次序,对定义在不同段中的变量,可以用同一个DS访问,但各段仍为独立段,通常将具有相同性质的段分在一个段组。举例:

DATA1SEGMENT‘DATA’

DATA1ENDSDATA2SEGMENT‘DATA’

…DATA2ENDSAA5GROUPDATA1,DATA2CODESEGMENT‘CODE’

ASSUMECS:CODE,DS:AA5START:MOVAX,AA5

MOVDS,AX;数据段地址赋给DS…

MOVAH,4CH

INT21H;返回DOSCODEENDSENDSTART简化的段定义

MASM5.0以上支持的段定义,不像SEGMENT定义得那么完善,但易用。简化段有利于汇编语言程序模块与高级语言程序模块的连接,但.COM程序不能用简化段定义。四、地址计数器伪指令

1.地址计数器$功能:指出汇编地址,是偏移量,记载下一个变量或指令在当前段中的偏移量。每个段开始时,$=0,随着汇编过程的进行而增值,每处理一条指令,$增加一个值,此值为该指令所需的字节数。允许直接引用$,如:JNE$+6;转向JNE指令的首地址加上6。$用于指令时,表示本条指令的第一个字节地址,$用于其他情况,表示$的当前值。2.ORG起始地址定义格式:

ORG表达式功能:定义指令或数据的起始地址,把表达式的值送给$(地址计数器)3.EVEN偶数地址定义功能:使下一个变量或指令从偶数地址开始,便于字存储对准(EVEN在代码段中可能多出一个NOP语句)。4.ALIGN边界定义格式:ALIGNn;n为2的幂次功能:使下一个变量或指令从n的接续整数倍地址开始,保证双字、四倍字对准。五、数据定义

格式:[变量名]操作符操作数[;注释]功能:为操作数分配存储单元,用变量与存储单元联系。为变量分配存储单元,并预置初值。操作符:

DB:一个操作数占有1个字节单元(8位),定义的变量为字节变量。

DW:一个操作数占有1个字单元(16位),定义的变量为字变量。

DD:一个操作数占有1个双字单元(32位),定义的变量为双字变量。

DF:一个操作数占有1个三字单元(48位),定义的变量为三字变量。

DQ:一个操作数占有1个四字单元(64位),定义的变量为四字变量。

DT:一个操作数占有1个五字单元(80位),定义的变量为五字变量。操作数:常数、表达式、字符串、?数据定义举例(1)

ORG200H;设置$DATA1DB12H,2+6,34HEVEN

;偶地址,使$指向偶地址DATA2DW789AHALIGN4

;4倍地址,使$指向4倍地址DATA3DD12345678HDATA4DW$,6699H

;$为汇编指针,16位,设置当前$(原$)的内容

吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十一讲数据定义举例(2)

ORG100HDATA1DB‘abcd’;字符串必须用单引号DATA2DB‘AB’DATA3DW‘AB’;按字处理,个数只能为≤2

数据定义举例(3)

ORG400HDATA1DB1,2,?,4

;按字节定义DATA2DW5,?,6;按字定义DATA3DF?;按三字定义DATA4DB8数据定义举例(4)ORG300HDATA1DB2DUP(12H,34H,56H)数据定义举例(5)ORG100HDATA1DB12H,34H,2DUP(56H,3DUP(9AH),78H)六、PROC、ENDP过程定义功能:用于定义子程序结构,过程名是CALL的操作数。格式:

过程名PROC[属性]…过程名ENDP属性:FAR,NEAR(默认值)吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十二讲七、模块连接伪指令

用于定义各模块之间的共享信息1.PUBLIC格式:PUBLIC符号1[,符号2,…]功能:公共引用,说明本模块定义,而其它模块引用的共享信息。2.EXTRN格式:EXTRN符号1:类型[,符号2:类型,…]功能:外部引用,说明其他模块定义,而本模块引用的共享信息。类型:对于变量,可以是字节(BYTE),字(WORD),双字(DWORD),三字(FWORD),四字(QWORD),五字(TWORD)。

对于标号、过程名,可以是段内引用型(FAR),段间引用型(NEAR)。共享信息是全局变量,包括常量、变量、标号、过程名等。EXTRN说明的信息应是在PUBLIC中已经定义的,否则出错。例:

PUBLICVAR1,VAR2EXTRNVAR1:WORD,VAR2:BYTE3.4操作数字段

操作数字段可以是寄存器、标号、变量、常数、表达式等。寄存器、标号、变量已作介绍,本节重点介绍常数、表达式。一、常数(1)

包括:数值常数、字符串常数、符号常数1.数值常数数值常数可以是二进制数、八进制数、十进制数、十六进制数。基数控制伪指令:改变基数默认值(原默认值为十进制)。格式:

.RADIX数值表达式功能:把默认的基数改变为2~16范围内的任何基数。例:

MOVBX,0FFH

等价于.RADIX16

MOVBX,178MOVBX,0FFH

MOVBX,178D2.字符串常数字符串常数:包括在单引号中的若干字符。字符串在存储器中储存的是相应字符的ASCII码。一、常数(2)

3.符号常数包括:EQU和=(1)EQU赋值伪指令格式:符号常数名EQU表达式功能:将表达式的值赋给符号常数。说明:表达式可以是有效的操作数格式,也可以是任何可求出数值常数的表达式,还可以是任何有效的符号(如操作符、寄存器名、变量名等)。EQU定义的一个符号常数名在程序中只能定义一次。例:

DATA1EQU88NEW_CXEQUCXDATA2EQUDATA1+12(2)=伪指令格式:符号常数名=表达式功能:将表达式的值赋给符号常数。=定义的一个符号常数名在程序中可以重复定义多次。例:…

DATA1=88…DATA1=DATA1+99

二、表达式(1)表达式:常数、寄存器、标号、变量与一些运算符相组合的序列。包括:数值表达式,地址表达式。1.运算符六种运算:算术运算、逻辑运算、移位运算、关系运算、返回值运算、属性运算。(1)算术运算符算术运算符:有5个,加(+)、减(-)、乘(×)、除(/)和取余(MOD)。(2)逻辑运算符逻辑运算符:4个,与(AND)、或(OR)、非(NOT)和异或(XOR)。二、表达式(2)(3)移位运算符移位运算符:2个,左移(SHL)和右移(SHR)。例:

MOVAL,0MOVBL,11011000BMOVAL,BLSHR3;(AL)=00011011BMOVCL,BLSHL6;(CL)=11000000B(4)关系运算符关系运算符:6个,等于(EQ)、不等(NE)、小于(LT)、大于(GT)、小于等于(LE)、大于等于(GT)。功能:关系运算符的两个操作数的计算结果应为逻辑值,结果为真(关系成立),表示为0FFFFH,结果为假(关系不成立),表示为0。例:

MOVAX,2LT7;(AX)=0FFFFH

二、表达式(3)(5)返回值运算符返回值运算符:5个,返回变量或标号的段地址(SEG)、返回变量或标号的偏移地址(OFFSET)、返回变量或标号的类型值(TYPE)、返回变量的单元数(LENGTH)、返回变量的字节数(SIZE)。①SEG返回变量或标号的段地址运算符格式:操作数SEG变量/标号功能:将变量/标号所在段的段基址值赋给操作数。②OFFSET返回变量或标号的偏移地址运算符格式:操作数OFFSET变量/标号功能:将变量/标号所在段中的偏移值赋给操作数。③TYPE返回变量或标号的类型值运算符格式:操作数TYPE变量/标号功能:将代表变量/标号类型的值赋给操作数。说明:如果是变量,则汇编程序将根据变量对应的数据定义伪指令回送类型值(即变量类型代表的字节数):DB为1,DW为2,DD为4,DF为6,DQ为8,DT为10。返回以字节数表示的类型,常数返回0。如果是标号,则汇编程序将回送代表该标号类型的数值:NEAR为-1,FAR为—2。二、表达式(4)④LENGTH返回变量的单元数运算符格式:操作数LENGTH变量功能:将代表变量的单元数赋给操作数。说明:<1>返回一次数据定义的第一个元素的长度,DUP时返回重复次数,其他情况返回1。<2>对于变量中使用DUP的情况,汇编程序将回送分配给该变量的单元数(按类型TYPE算),而对于其他情况,则均送1。只对DUP定义的变量有意义,返回分配给该变量的元素的个数。只返回第一个DUP前的元素个数,与DUP括号内的数据无关,认为只是一组数据而已,若与DUP并列地定义了其它数据,就只能返回1。⑤SIZE返回变量的字节数运算符格式:操作数SIZE变量功能:将代表变量的字节数赋给操作数。说明:<1>就是返回LENGTH×TYPE的结果。<2>汇编程序将回送分配给该变量的字节数。只对DUP定义的变量有意义。吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十三讲二、表达式(5)例:

DATA SEGMENTAT1000H

ORG3000HAA1 DW100DUP(0)BB1 DW1,2CC1 DB‘ABCD’DD1

DW1000DUP(2,3)EE1 DB50DUP(5,6)FF1 DW1,2,100DUP(?)GG1 DD5DUP(6DUP(?))DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATAHH1: MOVAX,DATA;AX=1000H MOVDS,AX MOVAX,SEGAA1;AX=1000H,AT定义

MOVBX,OFFSETAA1;BX=3000H MOVCL,TYPEAA1

;CL=2,字类型

MOVCH,TYPECC1

;CH=1,字节类型

MOVAL,TYPEGG1

;AL=4,双字类型二、表达式(6)

MOVDX,LENGTHAA1;DX=100,元素个数

MOVAX,SIZEAA1;AX=200,元素个数×类型

MOVDX,LENGTHBB1;DX=1,LENGTH只对DUP定义的变量有意义

MOVAX,SIZEBB1;AX=2MOVDX,LENGTHCC1;DX=1MOVAX,SIZECC1;AX=1MOVDX,LENGTHDD1;DX=1000MOVAX,TYPEDD1;AX=2000MOVDX,LENGTHEE1;DX=50MOVAX,SIZEEE1;AX=50MOVDX,LENGTHFF1;DX=1MOVAX,TYPEFF1;AX=2MOVDX,LENGTHGG1;DX=5MOVAX,TYPEGG1;AX=20…MOVAH,4CHINT21HCODEENDS

ENDHH1二、表达式(7)(6)属性运算符属性运算符:3个,临时改变类型属性运算符PTR、指定类型属性运算符THIS、定义类型属性运算符LABEL。①PTR临时改变类型属性运算符格式:类型PTR变量/标号功能:将PTR前面的类型临时赋给变量/标号,而原有段属性和偏移属性保持不变,其本身并不分配存储单元。说明:对于变量,可以指定类型BYTE、WORD、DWOR、DFWORD、QWORD、TWORD。对于标号,可以指定类型NEARFAR例:

DATADB66H,77HMOVAX,WORDPRTDATA

二、表达式(8)②THIS指定类型属性运算符格式:变量/标号EQUTHIS类型

功能:将变量或标号定义成指定的类型。说明:THIS指定的变量或标号本身并不分配存储单元,它与紧跟其后的变量或标号只有类型不同,而段地址和偏移量均相同。THIS指定类型与PTR相同。例:

DATA1EQUTHISBYTEDATA2DW1234H;DATA1和DATA2具有相同的段地址和偏移量,但类型值分别为1和2。

MOVAX,DATA2;AX=1234HMOVBL,DATA1;BL=34H二、表达式(9)③LABEL定义类型属性运算符格式:变量/标号LABEL类型功能:将变量或标号定义成指定的类型。说明:LABEL指定的变量或标号本身并不分配存储单元,它与紧跟其后的变量或标号只有类型不同,而段地址和偏移量均相同。THIS指定类型与PTR相同。例:

AA1LABELFAR

;AA1为段间转移入口

AA2:…;AA2为段内转移入口…

AA3LABELBYTEAA4DW1234HMOVAX,AA4MOVBH,AA3+1

二、表达式(10)2.数字表达式数字表达式:有常数、变量、标号与一些运算符相组合的序列。运算符可以是算术运算符、逻辑运算符、移位运算符、关系运算符、返回值运算符,但结果必须是常数。3.标号标号:指令所在单元的符号地址。标号的三种属性:段地址、偏移量、类型(NEAR、FAR)。4.变量变量:数据所在单元的符号地址。变量的五种属性:段地址(SEG返回值)、偏移量(OFFSET返回值)、类型(TYPE返回值)、单元数(LENGTH返回值)、字节数(SIZE返回值)5.地址表达式地址表达式:存储器地址,即EA的计算。是常数、变量、标号与一些运算符相组合的序列。吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十四讲3.5汇编语言程序设计及举例(1)

(一)

编写汇编语言程序的步骤1.

从实际问题抽象出数学模型。2.

确定解决此数学模型的算法。解决同一个问题可以有不同的算法。它们的效率可能有很大的差别。例如要做X*10,可以用乘法指令;也可以用X*8+X*2,而X*2或X*8也可以自身相加,或X左移来实现;这些方法的程序复杂程度和执行时间差别是很大的。又例如查表,是用线性查找还是用对分查找区别也很大。所以,确定合适的算法是很重要的。3.

画出程序流程图。把根据算法解决问题的思路和方法,用图形表示出来。4.

分配内存工作单元和寄存器。5.

根据流程图编制程序。当然,到这儿只是设计出了基本程序,此程序是否正确,可靠,还必须上机调试,排错和进行不要的检测。(二)

判断程序质量的标准为解决同一个问题所编制的程序,往往是多种多样的,如何衡量程序的质量呢?通常有三个标准:1.

程序的执行时间2.

程序所占用的内存字节数3.

程序的语句行数前两个标准是主要的,由于半导体存储器容量越来越大,成本急剧降低。3.5汇编语言程序设计及举例(2)

(三)

程序流程图在确定问题的算法以后,先不要急于写一条条指令,而要用程序流程图把编制程序的方法和思路勾画出来,确定程序的结构和相互之间的关系。本书中的流程图,采用以下一些惯用的画法。1.

用方框表示工作框,方框中用简明的语言标明所完成的特定功能。它有一个入口一个出口,用箭头表示。2.

用菱形表示判断框,菱形内标明比较,判断和条件。它有一个入口和几个出口,各用箭头表示。在各个出口处标明出口条件,条件成立则写“是(用Y表示)”,条件不成立用“否(用N表示)”。3.

程序中要调用的子程序或过程,用框表示,在框中标明子程序或过程的名字(包括入口地址、入口条件、参数、出口参数)。它有一个入口一个出口,各用箭头表示。带箭头的直线。程序的各框之间用箭头的直线连接起来,表示程序的走向。

算术运算程序设计(直线运行程序)

最简单的程序是没有分支,没有循环的直线运行程序。在8088/8086中,数据是16位的,它只有16位的运算指令,若是两个32位的数相乘就无法直接用指令实现(在80386中有32位数相乘的指令),但可以用16位乘法指令做4次乘法,然后把部分积相加来实现。其原理如图所示。算术运算程序设计(1)

例1:两个32位无符号数乘法程序若数据区中已有一个缓冲区存放了32位的被乘数和乘数,保留了64位的空间以存放乘积,能实现上述运算的程序流程图如图所示

算术运算程序设计(2)

相应的程序为:

name32bitmutiptydata segmentmulnumdw0000,0ffffh,0000,0ffffh,4dup(?)data endsstack segment parastack‘stack’ db 100dup(?)stack endscode segment assume cs:code,ds:data, ss:stack,es:datastart proc

farbegin: pushds ;DS中包含的是程序段前缀的起始地址

movax,0 pushax ;设置返回至DOS的段值和IP值

movax,data movds,ax moves,ax ;置段寄存器初值

leabx,mulnummulu32: movax,[bx];B->AX算术运算程序设计(3)

movsi,[bx+4]

;D->SI

movdi,[bx+6]

;C->DImulsi;B×Dmov[bx+8],ax

;保存部分积I mov [bx+0ah],dxmovax.,[bx+2];A->AX

mulsi;A×D addax,[bx+0ah]adcdx,0;部分积2的一部分与部分积1的相应部分相加

mov[bx+0ah],axmov[bx+0ch],dx;保存

movax,[bx]

;B->AX

muldi;B×Caddax,[bx+0ah]

;与部分积3的相应部分相加

adcdx,[bx+0ch]算术运算程序设计(4)

mov[bx+0ah],ax

mov[bx+0ch],dxpushf ;保存后一次相加的进位位

movax,[bx+2];A->AX

muldi ;A×C

popfadcax,[bx+0ch];与部分积4的相加部分相加

adcdx,0

mov[bx+0ch],ax

mov[bx+0eh],dx

retstartendpcodeends

endbegin吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十五讲算术运算程序设计(5)例2:32位符号数乘法在32位无符号数乘法程序的基础上很容易实现32位带符号数的乘法。首先设一个乘积的符号标志初值为0;检查被乘数,若为负,一方面对被乘数取补,另一方面对符号标志取反;再检查乘数,若是负数也对乘数取补和符号标志取反;然而调用32位无符号数乘法程序。最后检查乘积符号标志,若为负(即两个异号数相乘),则对64为乘积取补。程序流程图如图所示。算术运算程序设计(6)相应的程序为

name signed32bitmulptydata segmentsign db ?mulnum dw 0X1,X2,Y1,4dup(?)data endsstack segmentparastack‘stack’ db 100dup(?)stack endscode segment assumecs:code,ds:data,ss:stack;以下是主过程start proc farbegin: push ds mov ax,0 push ax ;为返回DOS设置返回地址算术运算程序设计(7)

mov ax,data mov ds,ax ;设置段寄存器初值

mov sign,0

;置符号为初值

lea bx,mulnum mov ax,[bx] ;B->AX mov dx,[bx+2] ;A->DX

mov si,[bx+4] ;D->SI

mov si,[bx+6];C->DI

cmp dx,0 ;检验正或负

jns other ;为正时转至OTHREnot axnot dx

add ax,1

adc dx,0 ;负则取补

notsign ;改变符号位

mov [bx],ax

mov [bx+2],dx ;暂存算术运算程序设计(8)other: cmp di,0 ;检查乘数符号

jns gomul ;为正时转至GOMULnot si

not di

add si,1

adc di,0 ;为负则取补

not sign ;实现符号运算gomul: call mulu32 ;调用32位无符号数乘法程序

cmp sign,0 ;检查乘积的符号

je done ;乘积为正则结束

not [bx+8] not [bx+0ah] not [bx+0ch] not [bx+0eh] add wordptr[bx+8],1 add wordptr[bx+0ah],0 adcwordptr[bx+0ch],0 adcwordptr[bx+0eh],0 ;乘积取补

done: retstart endp算术运算程序设计(9);以下是32位无符号数的乘法程序mul32 proc mov ax,[bx] mul si mov [bx+8],ax mov [bx+0ah],dx mov ax,[bx+2] mul si

add ax,[bx+0ah] adc dx,0 mov [bx+0ah],ax mov [bx+0ch],dx mov ax,[bx] mul di

add ax,[bx+0ah] adc dx,[bx+0ch] mov [bx+0ah],ax mov [bx+0ch],dx pushf算术运算程序设计(10)

mov ax,[bx+2] mul di popf adc ax,[bx+0ch] adc dx,0

mov [bx+0ch],ax mov [bx+0ch],dx

retmulu32 endpcode ends end begin分支程序设计(1)

在一个实际的程序中,程序始终是直线执行的情况是不多见的,通常都会有各种分支,例如变量x的符号函数用下式表示1 当x>0y=

0 当x=0

-1

当x<0在程序中,要根据x的值给y赋值如图所示。先把变量x从内存中取出来,执行一次“与”或“或”操作,就可以把x值的特征反映到标志位上。于是就可以判断是否等于零,若是,则令y=0;若否,再判断是否小于零,若是,则令y=-1;不是,就令y=1。相应的程序为:SIGEF:MOV AX,BUFFER OR AX,AX JE ZERO JNS PLUS MOV BX,0FFH JMP CONTIZERO: MOV BX,0 JMP CONTIPLUS: MOVBX,1CONTI:

分支程序设计(2)

例1:根据AL中的被置位的情况来控制转移到8个子程序R1~R8中的一个(在中断响应时,通过软件查询,从而转到相应的中断服务程序入口就类似于这种情况)。如果AL中为 00000001 则转至R1如果AL中为 00000010 则转至R2如果AL中为 00000100 则转至R3如果AL中为 00001000 则转至R4如果AL中为 00010000 则转至R5如果AL中为 00100000 则转至R6如果AL中为 01000000 则转至R7如果AL中为 10000000 则转至R8分支程序设计(3)

实现上述要求的程序框图如图所示我们可以把8个子程序的入口地址编成如图所示的分支表。

分支程序设计(4)

根据流程图可以写出下程序:

NAME BRANCH_PROGDATA SEGMENTBRTAB DW R11 ;子程序R1入口地址的IP值

DW R12 ;子程序R1入口地址的码段值

DW R21 DW R22 DW R31 DW R32 DW R41 DW R42 DW R51 DW R52 DW R61 DW R62 DW R71 DW R72 DW R81 DW R82DATAENDSSTACK SEGMENT PARASTACK‘STACK’ DB 100DUP(?)TOP EQU $-STACKSTACK ENDS分支程序设计(5)

CODE SEGMENTSTACK PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACKBEGIN: PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOVDS,AX MOV AX,STACK MOV SS,AX MOV AX,TOP MOV SP,AX LEA BX,BRTAB ;设跳转表的地址指针GTBIT: RCR AL,1 JC GETAD ;顺序检查AL中各位的状态

INC BX INC BX INC BX INC BX JMP GTBITGETAD: JMP DWORD PTR[BX] ;段间间接转移STARK ENDPCODE ENDS END BEGIN循环程序设计(1)在程序中,往往要求某一段程序重复执行多次,这时候可以利用循环程序结构。一个循环结构由以下几部分组成:

1.循环体:就是要求重复执行的程序段部分。其中又分为:循环工作部分和循环控制部分。循环控制部分每循环一次检查循环结束的条件,当满足条件时就停止循环,往下执行其他程序。

2.循环结束条件:在循环程序中必须给出循环结束的条件,否则程序就会进入死循环。常见的循环是计数循环,当循环了一定次数后就结束循环.在微型机中,常用一个内部寄存器(或寄存器对)作为计数器,通常这个计数器的初值置以循环次数,每循环一次令其减1,当计数器减为0时,就停止循环。也可以初值置0,每循环一次加1,再与循环次数相比较,若两者相等就停止循环。循环结束条件还可以有多种,下面结合例子分别介绍。

3.循环初态:用于循环过程中的工作单元,在循环开始时往往要置以初态,即分别给他们赋一个初值。循环初态又可以分成两部分,一是循环工作部分初态,另一是结束条件的初态,例如,要设地址指针,要使某些寄存器清零,或设某些标志等等。循环结束条件的初态往往置以循环次数。置初态也是循环程序重要的一部分,不注意往往容易出错。循环程序设计(2)在循环程序中,控制循环的方法因要求不同而有若干中。1.用计数器控制循环这是一种最常用也是最普通的循环控制循环的方法例1:在一串给定个数的数中寻找最大值(或最小值),放至指定的存储单元。每个数用16位表示。

NAME SEARCH_MAXDATA SEGMENTBUFFER DW X1,X2,XnCOUNT EQU $-BUFFERMAX DW ?DATA ENDSSTACK SEGMENT PARASTACK'STACK' DB 64DUP(?)TOP EQU $-STACKSTACK ENDSCODE SEGMENTSTART PROC FARASSUME CS:CODE,DS:DATA,SS:STACKBEGIN: PUSH DS MOV AX,0 PUSH AXMOV AX,DATA

MOV DS,AXMOV AX,STACK MOV SS,AX MOV AX,TOP MOV SP,AX MOV CX,COUNTLEA BX,BUFFER MOV AX,[BX] INC BXDEC CXAGAIN:CMP AX,[BX] JGE NEXT MOV AX,[BX]NEXT: INC BX LOOP AGAINSTART ENDPCODE ENDS END START循环程序设计(3)2.按问题的条件控制循环有些循环程序的循环次数是不知道或不确定的,而是要根据条件来确定是否循环,例如当满足条件时循环(或不循环),于是就要按条件控制循环例2:求一个16位(或32位)无符号数的整数平方根。所用的方法是逐次逼近的古典法(牛顿法).这种方法指出:若X1是数N的平方根的近似值,那么X2=(N/X1±X1)/2

是一个更接近的近似值。即若数N的平方根有确定的值。第一个近似值可使用公式(N/200+2)得到;用第一个近似值除N,然后对两个结果求平均值,就是第二个近似值;用它去除N再与第二个近似值求平均值就得到了第三个近似值……

例如,N=90000,则第一次近似值为: 90000/200+2=452 90000/452=199 (452+199)/2=326=X1;90000/326=276 (326+276)/2=301=X2; 90000/301=299 (301+299)/2=300=X3; 90000/300=300就可以确定90000的平方根为300。但是,并不是一个整数都具有整数的平方根,所以就要取近似值。怎么求得近似值呢?一种是控制逐次逼近的次数,例如要求逼近10次,就认为这个近似值以足够精确了;另一种是给定一个误差,只要相邻两次逼近所得值的差小于这个误差就停止计算。本例中按照第二种方法设计程序,给定误差为±1。所以,程序的循环要由给定的条件来控制。循环程序设计(4)能实现这种算法的程序流程图如图所示。根据流程,可写出如下程序:

name get_square_rootdata segmentnum dw 2710hresult dw ?digit equ 200data endsstack segment parastack'stack' db 100dup(?)stack endscode segment assume cs:code,ds:data,ss:stackstart proc farbegin: push ds

mov ax,0 push ax;为返回DOS设置返回地址

mov ax,data mov ds,ax mov ex,ax ;置段寄存器

lea bx,num mov ax,[bx]循环程序设计(5)

mov si,ax mov di,digit cwd

div di ;第一次试探N/200 add ax,2 ;AX中为第一次试探值conti: mov cx,ax mov ax,si ;N->AX cwd

div cx

add ax,cx shr ax,1 ;得到新的试探值

mov dx,ax ;与上一个试探值比较

sub dx,ax ;相等则结束循环

je done ;若差为±1也结束循环

cmp dx,1 je done

cmp dx,-1 jne contidone: mov [bx+2],ax;存结果

retstart endpcode ends end begin由于在8088中,数是用整数表示的,所以用上述办法求平方根的应用范围是十分有限的。若要求实数的平方根就要用8087数值协处理器。吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十七讲循环程序设计(6)例3:规格化一个二进制数在8088中数是以二进制整数表示的,8位带符号二进制整数的表示范围为-128<=X<=+127,16位带符号二进制整数的表示范围为-32768<=X<=+32767是非常有限的。为了扩展数的表达范围,提高有效数的表达精度,通常采用浮点表示法。浮点表示法与科学计算中的数的表示法相一致,即把数分为阶和尾数两部分。例如X=a*2^b,其中a即为由若干位二进制数构成的尾数,而b则为由若干位构成的阶。通常尾数和阶都是可正可负的。为了提高有效数的位数,尾数通常应该是规格化的。循环程序设计(7)下面举例简要地说明一种浮点表示法。这里谈到的浮点数由4个字节(32位)组成,用一个字节表示阶,另三个字节表示尾数。阶和尾数都是带符号数,阶的最高位是符号位,剩下的7位为阶的二进制值;尾数具有22位二进制小数,最高两位作为符号位,整个数可表示如下:循环程序设计(8)若X=a*2^b,则1.若X=0, a=0 b=02.若X>0, 1/2<=a<1 -128<=b<=+1273.若X<0, -1<=a<-1/2 -128<=b<=+127所以能表示的X的数值范围为:2^-128<|X|<2^+127也即 1.47^-39×10<|X|<|X|<1.7×10^+38这就大大超出了32位二进制整数所能表达的范围。例如有一个十进制数+123.567,用科学计数法表示,若尾数的有效位数为6位,则可表示为+0.123567E3+0.012356E4+0.001235E5……循环程序设计(9)显然,第一种表示有效位数是6位,这是最精确的;而第二种表示有效位数只有5位,尾数的最前面包含了一个0;第三种表示有效位数只有4位,尾数的最前面包含了两个0,后两种情况都是属于尾数未规格化的。对于二进制数来说也是如此,规格化能提高尾数中的有效位的位数。对于正数来说,小数点后第一位(即尾数的最高位,在我们的例子中即为d21位)必须为1;对于负数来说必须为0。为了使数规格化,就需要对尾数进行移位,则阶也必须相应有所增减。规格化的考虑如下:

1.若尾数为0,则阶也置0。

2.若尾数的符号位(d23,d22)为01...(正数),或10...(负数),尾数必须右移一位,且阶加1。在这个移位过程中d23位的值不变。

3.若尾数的最高有效位为000...(正数)或111...(负数),尾数必须左移,直至最高有效位为001...(正数)或110(负数)。且移位的次数必须从阶中减去。循环程序设计(10)下面是一个使尾数向上规格化(左移)的程序例子,并记下了为了实现规格化使尾数左移的次数,其程序流程图如图所示。相应的程序为:

name normalize_digitaldata segmentnum ddX

;定义未规格化的尾数nornum dd?

;为规格化的尾数保留的存储单元shcout db?

;为移位辞书保留的存储单元data endsstack segment parastack'stack‘ db 100dup(?)stack endscode segment assume cs:code,ds:data,ss:stackstart procfar begin: push ds mov ax,0 push ax

mov ax,data

mov ds,ax

mov c1,0 ;置移位次数初值

lea bx,num循环程序设计(11)

mov ax,[bx] mov dx,[bx+2]

;把32位数取至DX,AX中

cmp dx,0

;已规格化否

jle done

;是,结束again:inc c1

sal ax,1 rcl dx,1 ;否,整个32位数左移1位

and dx,dx jns again ;尚未规格化循环done:

mov shcout,c1 mov [bx+4],ax mov [bx+6],dx;保存结果

retstart endpcode ends end begin循环程序设计(12)3.多重循环程序常常在一个循环中包含另一个循环,这就是多重循环,例如多维数组的运算就用到多重循环。下面介绍一个延时程序作为多重循环的例子。系统中许多动作是有次序的,而且有一定的时间要求,就要求延时。执行一条指令是需要时间的(由指令表可以查到指令的执行时间),由若干条指令形成循环程序就可以形成一定时间,精心选择指令和安排循环次数可以得到所需的延时时间。下面是一个多重循环的例子(没有精确计算延时时间)

DELAY:MOV DX,3FFHTIME:MOV AX,0FFFFH

TIME1:DEC AX NOP JNE TIME1 DEC DX JNE TIME RET循环程序设计(13)4.用开关变量控制循环在有些情况下,可能在一个循环中有两个循环支路,在第一个支路循环了若干次以后,转至另一个支路循环。这就可以设一个开关变量,用以控制转入不同的循环支路。例4:若在某一数据采集系统中,采集到的前5个量,用一种函数进行处理;而采集到的后7个量,用另一种函数进行处理。若采集到的数据放在缓冲区BUFFER中,处理后的数据放在BLOCK缓冲区中。第一种处理函数为子程序FUN1,第二种处理函数为子程序FUN2。在程序中设置一个开关(即标志),其初值为0,控制进行第一种处理;在处理了5个数据,使开关置为1,控制进行第二种处理,在处理了7个数据后恢复初始状态。其流程图如图所示。循环程序设计(14)相应的程序为:

name loop_use_swichdata segmentbuffer dw 05,05,05,05,05,05,05,05,05,05,05,05block dw 12dup(?)count1 equ 5count2equ 7data endsstack segment parastack‘stack’ db 100dup(?)stack endscode segment assume cs:code,ds:data,ss:stackstart proc farbegin:push ds mov ax,0 push ax

;为返回DOS,设置返回地址

循环程序设计(15)

mov ds,ax

mov es,ax ;置段寄存器初值

mov dx,0 ;置开关量初值

mov cx,count1+1 lea bx,buffer lea si,blockagain: mov ax,[bx]

cmp dx,0 ;开关量是否为0

jne anoth ;不为0,转至ANOTHERcall fun1 loop next

mov dx,1 ;开关量转为1

mov cx,count2+1

jmp againnext: mov [si],ax

inc bx

inc bx

inc si

inc si jmp again

anoth: call fun2 loop next retstart endpfun1 proc add ax,ax ;FUN1举例1

retfun1 endpfun2 procadd ax,ax add ax,ax ;FUN2举例

retfun2 endpcode ends end begin循环程序设计(16)5.用逻辑尺控制循环在上例中,若选用不同处理函数的顺序不规则,例如第1、2、5、7、10这几个测量值用第一种处理函数,而第3、4、6、8、9、11、12这几个测量值用第二种处理函数,这时循环可以用一个位串来控制,此位串从最高位开始若为0则采用第一种函数,若为1则采用第二种函数,在程序中每循环一次把此位串左移一位,把控制位移至标志C中,由C的值控制转至不同的分支。这样能实现上述控制要求的位串为0011010110110000,这个位串就称为逻辑尺,可放在某一寄存器中。其流程图如图所示。循环程序设计(17)例5:由流程图可编出如下程序:

name loop_use_logic_ruladata segment buffer dw11,22,33,44,55,66,77,88,99,1234,5678,9876block dw 12dup(?)count equ 12logrul equ 0011010110110000bdata endsstack segment parastack‘stack’ db 100dup(?)stack endscode segment assume cs:code,ds:data,es:data,ss:stackstart proc farbegin:push ds mov ax,0 push ax mov ax,data mov ds,ax mov es,ax循环程序设计(18)

mov dx,logrul mov cx,count lea bx,buffer ` lea si,blockagain: mov ax,[bx] rcl dx,1 ;逻辑尺左移1位

jc anoth

call fun1next: mov [si],ax inc bx

inc bx

inc si

inc si

loop again retanoth: call fun2

jmp nextstart endpfun1 proc add ax,ax retfun1 endpfun2 proc add ax,ax add ax,ax retfun2 endpcode ends end begin吉林大学远程教育学院微机原理及汇编语言

主讲人:赵宏伟教授总学时:80

吉林大学计算机科学与技术学院

第二十八讲字符串处理程序设计(1)计算机经常要处理字符,常用的字符编码是ASCII码。在使用ASCII码字符时,要注意以下几点:

1.ASCII码的数字和字符形成一个有序序列。例如数字0~9为的ASCII码为30H~39H,大写字母A~Z的ASCII码为41H~5AH等。

2.计算机并不区分可打印的和不可打印的字符,只有I/O装置(例如显示器、打印机)才加以区分。

3.一个I/O装置只按ASCII码处理数据。例如要打印数码7,必须向它送ASCII码37H,而不是07H。若按数字键9,键盘送至主机的是9的ASCII码39H。

4.许多ASCII装置(例如键盘,显示器,打印机等)并不用整个ASCII字符集。例如有的忽略了许多控制字符和小写字母。

5.不同的设备对ASCII控制字符的解释往往不同,在使用中要注意。

6.

一些广泛使用的控制字符为:0AH

换行(LF)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论