




已阅读5页,还剩182页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2020年1月14日 第4章汇编语言程序设计 4 2汇编语言语法 4 3实模式下的汇编语言程序设计 4 4汇编程序及上机过程 4 5DOS及BIOS功能调用 4 6任务切换与混合语言编程 2020年1月14日 4 1计算机程序设计语言的发展 1 机器语言 MachineLanguage 任何计算机实际上只能直接识别设计微处理器时所规定好的 一整套用 0 1 数字代码表示的机器指令 直接用机器指令来编制计算机程序的方法就称为机器语言程序设计 2020年1月14日 二进制数形式的指令和数据如B064H 既不直观 又不易理解和记忆 1011000001100100 机器语言 2 汇编语言 AssemblyLanguage 和机器语言相比 使用汇编语言来编写程序可以用助记符来表示指令的操作码和操作数 也可以用标号和符号来代替地址 常量和变量 例 B064是机器语言 什么意思 MOVAL 64H 容易记忆理解 这就是助记符 助记符 用便于记忆的英语单词表示的指令操作码 它反映了指令的功能和主要特征 便于人们理解和记忆 2020年1月14日 汇编程序 汇编源程序需翻译成机器语言 变成可执行文件 机器才能执行 这个翻译过程叫汇编 高级语言中称该过程为 解释 或 编译 执行翻译的程序称为 汇编程序 源程序的编译程序 汇编程序 汇编语言源程序 机器语言目标程序 2020年1月14日 3 高级语言 Highlevellanguage 如BASIC FORTRAN C语言等 这些高级的程序设计语言 使用了更接近于人们的自然语言 英语 和习惯的教学语言来描述算法的执行过程 从而使编写的程序更加直观和简练 这些高级语言通常都包含有各种函数计算 字符串处理 数据I O等功能 所以程序的编写 阅读和修改变得相当容易掌握和使用 2020年1月14日 高级语言一般总是独立于具体机器的 高级语言必须借助于更强有力的翻译系统 编译程序 Compiler 才能将源程序转换成相应的机器语言目标程序 与汇编程序不同 此处一条最简单的高级语言语句 可能对应着一组机器指令 2020年1月14日 4 为什么要用汇编语言编写程序 汇编语言非常接近机器语言程序 通过编制汇编语言程序 可以更清楚地了解计算机的工作过程 现在的微机系统中 底层的一些功能仍然靠汇编语言程序来实现 汇编语言程序的效率通常高于高级语言程序 2020年1月14日 4 2 1汇编语言语句格式 汇编语言源程序通常由一个或几个程序模块组成 每个模块一般由三个逻辑段组成 数据段 存放数据 变量堆栈段 堆栈区域代码段 存放程序指令 4 2汇编语言语法 2020年1月14日 汇编语言的语句有两种 指令性语句由8086指令助记符构成的语句名称 指令助记符目的操作数 源操作数 注释指示性语句由伪指令构成的语句名称伪指令操作数1 操作数2 操作数n 注释各部分之间至少要用一个空格作为分隔符 指令性语句与指示性语句比较 指令性语句由CPU执行 每一条指令性语句都有一条机器码指令与其对应指令性语句汇编时生成机器码指示性语句由汇编程序执行 它指出汇编程序应如何对源程序进行汇编 如何定义变量 分配存储单元以及指示程序开始和结束等 指示性语句无机器码指令与其相对应指示性语句汇编时不生成机器码 2020年1月14日 4 2 1汇编语言语句格式 汇编语言语句通用格式如下 名称 前缀指令 助记符 操作符 注释 名称 名称是一个标识符 它可以是标号 也可以是变量名 段名和子程序名 名称后面是 则该名称表示标号 名称后面是空格 则名称可能是标号 也可能是变量 标号表示指令的符号地址 变量表示内存中某一存储单元的地址 2020年1月14日 在有些指令语句中 需要在助记符前加前缀指令 例如LOCK或REP 中间应用空格使两者分开 如REPMOVSB 助记符 这是为指令操作码规定的符号 任何指令语句都需要此部分 它表示了指令语句的基本操作功能 如MOV是传送指令的助记符 ADD是加法指令的助记符 2020年1月14日 操作数 操作数可以根据指令的功能需要 可不带操作数 带1个操作数或2个操作数 若有两个操作数时 中间用 号分开 例如 NOP ADDBL 30H 而操作数与助记符之间必须以空格分隔 注释 注释是为方便程序人员阅读程序而加的说明 它既不影响源程序的汇编 也不会出现在目标程序中 通常并不要求每个汇编语句都应加注释 2020年1月14日 注释以分号开头 可放在指令后 也可单独一行 注意注解的写法 要写指令 段 在程序中的作用 而不要写指令的操作 如 1 MOVCX 100 传送100到CX2 MOVCX 100 循环计数器置初值显然 第二种写法要比第一种写法要好 2020年1月14日 4 2 2汇编语言语句的数据项 常数 常数就是指令中出现的那些固定值 可以分为数值常数和字符串常数两类 例如 立即数寻址时所用的立即数 直接寻址时所用的地址 ASCII字符等都是常数 汇编语句中的数值常数的第一位必须是数字 否则汇编时将被看成是标识符 例如常数B7H在语句中应写成0B7H 字符串常数是由单引号 括起来的一串字符 例如 ABCDEFG 单引号内的字符在汇编时都以ASCII的代码形式存放在存储单元中 上述字符串其ASCII代码分别为41H 42H 43H 44H 4BH 字符串最长允许有255个字符 2020年1月14日 数值常量二进制数 以B结尾 如01001101B十进制数 如85十六进制数 以H结尾 第1个数字为A F时 前面应加0 如0F160H字符串常量 用引号括起来的1个或多个字符 如 ERROR a 汇编时被翻译成对应的ASCII码45H 52H 52H 4FH 52H 21H和61H 标号 标号是用符号表示的地址 称为符号地址 用以指示此指令语句所在的地址 即指令所在内存单元的符号地址标号有3个属性 段地址 偏移地址和类型 标号的段地址和偏移地址属性是指标号对应的指令首字节所在的段地址和段内的偏移地址 标号的类型属性有两种 NEAR和FAR类型 2020年1月14日 类型 NEAR 表示标号所在语句与转移指令 调用指令在同一码段内 跳转时只需改变IP即可 默认类型FAR 标号所在语句与转移指令 调用指令不在同一代码段内 标号通常作为转移指令或CALL指令的转移地址 变量 变量是与一个数据项的第一字节相对应的标识符 它表示该数据项第一字节在现行段中的偏移量 即内存中的存储单元或数据区 变量的值在程序运行期间可随时修改 变量具有3个属性 段地址 SEG 变量所在段的段地址 偏移地址 OFFSET 变量所在段内的偏移地址 类型 TYPE 变量的类型是所定义的每个变量所占据的字节数 2020年1月14日 在汇编语言中 变量是通过伪指令来定义的 其格式如下 变量名DB表达式 定义字节变量 变量名DW表达式 定义字变量 变量名DD表达式 定义双字变量 变量名DQ表达式 定义长字变量 变量名DT表达式 定义一个十字节变量 2020年1月14日 上述伪指令格式中的表达式可以有以下几种情况 一个或多个常数或某个运算公式 其值应为常数 带引号的字符串用问号作为表达式带DUP 重复方式 表达式地址表达式 只能用于DW或DD 2020年1月14日 当用DW定义地址表达式时 地址表达式中的变量名称表示该变量的第一个存储单元的偏移地址 地址表达式中的标号表示它所代表的指令 或伪指令 的第一个字节的偏移地址 当用DD定义地址表达式时 低位字用于预置偏移地址 高位字用于预置段地址 这些数值都是在定位时装入的 2020年1月14日 地址表达式中的变量或标号可与常数值相加减 对于变量来说 运算结果的类型不变 对标号来说 运算结果仍表示原标号所在段中的偏移地址 变量或标号不能与变量或标号相加 但可相减 结果是没有属性的纯数值 2020年1月14日 DATA BDB10 5 10HDATA WDW100H 4DATA DDD0FFFBH 05H 10H 00H 01H FCH FFH FBH FFH 00H 00H 0AH DATA B DATA W DATA D 10 5 10H 100H 4 0FFFBH 汇编后的内存分配情况图 例 操作数可以是字符串 例如STRDB HELLO 汇编后的情况如图 STR H E L L O 注意下面两个定义的不同之处 DB AB 41H在低字节 42H在高字节DW AB 42H在低字节 41H在高字节 48H 45H 4CH 4CH 4FH 2020年1月14日 例 RSVDW 操作数 用来保留存储空间 但不存入数据 重复的数据可以使用复制操作符DUP 亦可写成 RSVDW8DUP 2020年1月14日 例 TABLEDB10DUP BUFFERDWTABLE 3 表示地址计数器的当前值若TABLE的偏移地址为0080H BUFFER 0080H 80H TABLE 008AH008BH008CH008DH 8FH 00H 00H 0089H 10Bytes 4 表达式 表达式由操作数和运算符组成 操作数一个操作数在内容上可能代表一个数据 也可能代表一个存储单元的地址 运算符用一个运算符可以对一个或几个操作数进行运算 构成一个表达式 源程序中表达式经汇编后为一个值 2020年1月14日 汇编语言中有4类运算符 算术运算符 逻辑运算符 关系运算符 属性操作符 2020年1月14日 算术运算符 包括加 减 乘 除 和取模运算 MOD 取模运算是取两数相除的余数 但两操作数必须为正整数 82MOD16结果为2对地址值的运算操作一般应采用在标号上加 减某一个数字量来表示一个存储单元的地址 2020年1月14日 例如用于数字表达式 MOVAX 4 1024汇编后的形式为 例如用于地址表达式 LEASI TAB 3若TAB的偏移地址为1000H 则汇编后的形式为 MOVAX 4096 LEASI 1003H 逻辑运算符 包括与 AND 或 OR 非 NOT 和异或 XOR 逻辑运算符只能用于数字表达式中例 MOVCL 36HAND0FH经汇编后 注意 不要把逻辑运算符与逻辑运算指令混淆例 ANDAX 3FC0HAND0FF00H汇编后源操作数被翻译为 所以上述指令与等价 MOVCL 06H 3F00H ANDAX 3F00H 2020年1月14日 关系运算符 相等EQ Equal 不等NE NoEqual 小于LT LessThan 大于GT GreaterThan 小于或等于LE LessthanorEqual 大于或等于GE GreaterthanorEqual 关系运算的结果是一个逻辑值 真或假关系为真 结果为全1关系为假 结果为全0 2020年1月14日 例 MOVBX PORTGT300H若PORT的值大于300H 则汇编后为 否则汇编后为 MOVBX 0FFFFH MOVBX 0 2020年1月14日 属性操作符 利用获取属性操作符可以把一个存储单元地址分解为段地址和偏移量 利用重新定义类型操作符可以规定存储单元的性质 获取属性操作符有OFFSET SEG TYPE SIZE和LENGTH重新定义类型操作符有PTR 2020年1月14日 取地址运算符 SEG OFFSET SEG 取变量 标号的段地址OFFSET 取变量 标号的偏移地址例 VARDB12H MOVBX OFFSETVAR 取变量VAR的偏移地址MOVAX SEGVAR 取变量VAR的段地址 2020年1月14日 注意以下指令 MOVBX OFFSETVAR等价与LEABX VAR 2020年1月14日 取值运算符 TYPE LENGTH SIZE TYPE取变量的类型 1 2 4 LENGTH对于变量中使用DUP的情况 取所定义变量的长度 即变量中元素的个数 SIZE计算一个变量存储区所占用的字节数 TYPE LENGTH 例 VARDW1 2 3 4 5则TYPEVAR 2 2020年1月14日 重新定义类型操作符 PTR 用来指定地址操作数的类型格式 PTR类型 BYTE WORD DWORD NEAR FAR BYTE WORD DWORD用于描述数据存储单元 变量 地址NEAR FAR用于描述转移 调用的目的地址 标号 2020年1月14日 例 MOVBYTEPTR DI 0 字节类型MOVWORDPTR DI 0 字类型PTR也可用来进行强制类型转换例 STR1DW STR1定义为字类型MOVAX STR1 合法MOVAL STR1 非法MOVAL BYTEPTRSTR1 合法 2020年1月14日 OPE1DB1 2OPE2DW2233H 5566HMOVAX OPE1 1MOVAL OPE2 MOVAX WORDPTROPE1 1MOVAL BYTEPTROPE2 AX 3302H AL 33H 4 2 3伪指令 伪指令是在汇编期间由汇编程序执行的操作 如处理器选择 定义数据 分配存储空间 定义段 指示程序结束等 另外 有关子程序定义 访问外部标识符等伪指令将放在后面相关章节中介绍 1 段定义伪指令 汇编语言程序是按段来组织程序和数据的 和存储器的物理段相对应 汇编语言程序中的段称为逻辑段 汇编连接后被映射到物理段中 三类段 代码 程序 数据 堆栈段定义伪指令 SEGMENT ENDS ASSUME 定义一个段的基本格式 段名SEGMENT 定位类型 组合方式 类别 段名ENDS 2020年1月14日 SEGMENT和ENDS伪指令 这两个伪指令总是成对出现 二者前面的段名应一致 SEGMENT说明了一个段的开始 ENDS说明了一个段的结束 对数据段和堆栈段 段中的语句一般是变量定义 对代码段则是指令语句 例 CODESEGMENTCODEENDS SEGMENT语句后可以带有可选参数 用以规定逻辑段的其他一些属性 1 定位类型说明如何确定逻辑段的边界 有四种 PARA Paragraph 逻辑段从某一个节 16个字节 的边界开始 即段的起始地址应能被16整除 或这说段起始物理地址应为 0H 默认类型BYTE 逻辑段从字节边界开始 即段可以从任何地址开始 WORD 逻辑段从字边界开始 即段的起始地址必须是偶数 PAGE 逻辑段从页边界开始 256字节称为一页 故段的起始物理地址应为 00H 2 组合类型 说明不同模块中同名段的组合方式 PUBLIC 所有此类型的同名段组合成一个逻辑段 公用一个段地址 运行时装入同一个物理段中 COMMON 所有此类型的同名段具有相同的起始地址 覆盖 共享相同的存储区域 AT 按绝对地址定位 段地址就是表达式的值 STACK 专用于说明堆栈段 组合方式同PUBLIC 3 类别 用单引号括起来的字符串 所有同类别的段被安排在连续的存储区域中 例 在模块1中有段定义 seg1SEGMENTPARASTACK stack seg1ENDS在模块2中有段定义 seg2SEGMENTPARASTACK stack seg2ENDS则连接时这两个段被安排在一起 2020年1月14日 ASSUME伪指令 在代码段中 还必须明确段和段寄存器的关系 这由ASSUME语句来指定 ASSUMECS code DS data ES data语句中的code和data为段名 这个语句说明 CS将指向名字为code的代码段DS和ES将指向名字为data的数据段 2020年1月14日 但要注意 ASSUME伪指令只是告知汇编程序有关段寄存器与段的关系 并没有给段寄存器赋予实际的初值 故下面的语句MOVAX DATAMOVDS AX将段基址装入段寄存器 如果程序中用到堆栈段 则SS也需装入实际的初值 代码段基地址不需要程序员装入CS寄存器 而由OS负责装入 2020年1月14日 2 源程序结束伪指令END 汇编语言源程序的最后 要加汇编结束伪指令END 以使汇编程序结束汇编 格式 END 表达式 END后跟的表达式通常就是程序第一条指令的标号 指示程序的启动地址 要执行的第一条指令的地址 2020年1月14日 3 简化段定义伪指令 1 8086 在这条伪指令后 汇编程序将在8086 8088方式下操作 实际上这是微处理器的默认操作状态 2 386 在这条伪指令后 汇编程序将在80386方式下操作 如果想利用32位寄存器 必须加上这条伪指令 2020年1月14日 5 赋值伪指令EQU 在汇编语言程序中 当某个表达式被多次引用时 常采用给这个表达式赋予一个名称 这样源程序中就可以以名称代替表达式 另外常使用标号来代表数据 数据地址或程序地址 这种赋予表达式或数据 地址以名称 标号的伪指令EQU有两种格式 表达式名称EQU表达式 新标号EQU老标号 2020年1月14日 用EQU定义的符号未清除前 不能重新定义 清除EQU定义可用PURGE伪指令 不占用存储空间 仅是给符号赋值 2020年1月14日 FIVEEQU5COUNTEQUCXTENEQU10DISTEQUBYTEPTR SI BP MOVAX TENMOVAX COUNTADDDIST FIVE 定义 引用 2020年1月14日 6 定义名称类型伪指令LABEL 本条伪指令用于定义标号名称和属性 它和下一条指令共享存储器单元 格式 名字LABEL类型 例 BYTE ARRAYLABELBYTE WORD ARRAYDW100DUP 7 地址计数器伪指令 伪指令 用来表示当前正在汇编的指令的地址 如 LENEQU STR1 2020年1月14日 ORG伪指令 ORG规定了段内的指令或数据存放的开始地址 偏移地址的初值 其格式为 ORG表达式的值即为开始地址 从此地址起连续存放程序或数据 例 ABCSEGMENTORG1000Hbegin ABCENDS 指令从1000H开始存放 2020年1月14日 ORG伪指令举例 例 写出以下数据段中各量的偏移地址DataSEGMENTORG10HVar1DB 12345 Var1的偏移地址为10HORG40HVar2DW8000H Var2的偏移地址为40HVar3DB 1ORG200H Var3的偏移地址为42HVar4DB1 2 3 4 5 Var4的偏移地址为200HDataENDS 2020年1月14日 8 定义结构的伪指令STRUC ENDS 结构的定义 结构伪指令的格式如下 结构名称STRUC 结构名称ENDS如果DB DW或DD语句包括变量标识符 则该标识符表示一个字段的开始 称为字段标识符 由DB DW DD伪指令所组成的语句序列 2020年1月14日 结构的存储分配和预置 为了给结构分配存储空间或预置 必须有一个援用该结构的语句 其格式如下 变量结构名称 赋值说明 对结构的访问 通过援用语句对结构进行存储空间分配和预置之后 结构及其字段就以变量的形式出现 可以像使用其它变量一样使用 但对结构的访问必须用变量路径名的方法进行 路径名的格式为 变量名 字段名 2020年1月14日 9 IFELSEENDIF条件汇编伪指令 MASM提供了功能强大的条件汇编伪指令 使用它的一般格式是 IF 如果条件成立 ELSE 否则 ENDIF 结束条件汇编语句 10 过程定义伪指令PROC ENDP 过程就是子程序 一个过程可以被其它程序所调用 用CALL指令 过程的最后一条指令一般是返回指令 RET 过程定义伪指令的格式为 PROC 类型 RETENDP注意 PROC和ENDP必须成对出现 过程的类型有两种 NEAR 默认类型 表示段内调用FAR 表示段间调用调用一个过程的格式为 CALL 2020年1月14日 11 访问外部标识符的伪指令EXTRN PUBLIC 当把若干个模块连接在一起时 必须解决其中的任一模块能够引用其它模块中的某些变量或标号的问题 这里引入的定义访问外部标识伪指令EXTRN和PUBLIC就是提供解决这个问题的方法 EXTRN和PUBLIC伪指令语句的格式如下 EXTRN标识符 类型 标识符 类型PUBLIC标识符 标识符 EXTRN伪指令语句中的标识符表示是外部的变量或标号 而PUBLIC伪指令语句中的标识符表示可供其它模块引用的变量或标号 在EXTRN伪指令中 若标识符为标号 则类型有NEAR或FAR 若标识符为变量 则类型有BYTE WORD或DWORD 2020年1月14日 4 2 4宏指令及其使用 宏定义伪指令如果需要多次使用同一个程序段 可以将这个程序段定义为一个 宏指令 然后在需要时 可简单地用宏指令名来代替这个程序段指令的格式为 MACRO 形参表 ENDM 例 两个数之和的宏定义和宏调用 宏定义为 DADDMACROX Y ZMOVAX XADDAX YMOVZ AXENDMX Y Z是形式参数 调用宏DADD时可写为 DADDDATA1 DATA2 SUMDATA1 DATA2 SUM是实际参数 由它们替换定义中的X Y Z 宏调用与过程 子程序 调用都是一次定义 多次调用 它们之间的差别是 执行形式 宏命令伪指令由宏汇编程序在汇编过理中进行处理 而CALL RET则是由CPU执行的指令 汇编结果 宏命令伪指令汇编后被展开 执行速度 宏命令执行速度较快 因无调用转移 占用内存 宏指令简化了源程序 但不能简化目标程序 并不节省内存单元 使用过程可以节省代码占用的内存空间 宏展开 汇编程序会把宏调用按宏定义展开例如 宏定义为 DISPLAYMACROstringLEADX stringMOVAH 9INT21HENDM程序中宏调用 DISPLAYERROR MESSAGEDISPLAYEXIT MESSAGE 汇编后的结果 带有 号的指令为宏展开后的结果 LEADX ERROR MESSAGE MOVAH 9 INT21H LEADX EXIT MESSAGE MOVAH 9 INT21H 宏定义将某个寄存器的内容向左或向右移若干位 SHIFTMACRON REG CCMOVCL NS将AX的内容算术左移4位宏展开SHIFT4 AX AL1MOVCL 41SALAX CL 2020年1月14日 4 3实模式下的汇编语言程序设计 通常编制一个汇编语言程序应按如下步骤进行 明确任务 确定算法 绘流程图 根据流程图编写汇编语言程序 上机调试程序 源程序的基本结构 顺序 分支 循环 子程序 2020年1月14日 1 用方框表示工作框 框中用简明语言标明要完成的功能 2 用菱形框表示判断框 框中标明比较 判断和条件 如何绘制程序框图 流程图 N Y 2020年1月14日 4 各框之间用直线连起来表示程序走向 3 起始和终止框 stackSEGMENT stack DB256DUP stack stackENDSdataSEGMENTdataENDScodeSEGMENTASSUMECS code DS data SS stackstart MOVAX dataMOVDS AXMOVAL 4CHINT21HcodeENDSENDstart 堆栈段 数据段 代码段 一个基本的汇编语言程序框架 例4 4 求X 4 结果放在RESULT中 完整源程序如下 2020年1月14日 4 3 1顺序程序设计 2020年1月14日 例6 5试编制一程序 求出下列公式中的Z值 并存放在RESULT单元中 其中X Y的值分别存放在VARX VARY单元中 源程序编制如下 1DATASEGMENT 2VARXDW6 3VARYDW7 4RESULTDW 5DATAENDS 2020年1月14日 6STACKSEGMENTSTACK 7DB10DUP 8STACKENDS 9CODESEGMENT 11ASSUMECS CODE DS DATA SS STACK 12START MOVAX DATA 13MOVDS AX 14MOVDX VARX DX X 2020年1月14日 2020年1月14日 结束用户程序 返回操作系统的一个办法是用中断指令 INT21H 如使用这种办法 用户程序可以不设置过程 只要在用户程序结束时 用以下两条指令即可 MOVAH 4CH INT21H 2020年1月14日 例4 6用查表的方法将一位十六进制数转换成与它相应的ASCII码 既然指定用查表的方法 那么首先要建立一个表TABLE 我们在表中按照十六进制数从小到大的顺序放入它们对应的ASCII码值 编制的源程序如下 DATASEGMENT TABLEDB30H 31H 32H 33H 34H 35H 36H 37H DB38H 39H 41H 42H 43H 44H 45H 46H HEXDB4 ASCIDB DATAENDS STACK1SEGMENTSTACK DW20HDUP 0 2020年1月14日 STACK1ENDS COSEGSEGMENT ASSUMECS COSEG DS DATA SS STACK1 BEING MOVAX DATA MOVDS AX MOVBX OFFSETTABLE MOVAH 0 MOVAL HEX XLATMOVASCI AL MOVAH 4CH INT21H COSEGENDS ENDBEING 字节转换指令 XLAT表首址 指令功能 AL BX AL 使用这条指令 通常是把表首址的偏移量送入BX中 而把要查找表内单元的偏移量 0 255 送入AL中 这样 上述程序中代码段的有关语句可以修改为ADDBX AX MOVAL BX 2020年1月14日 2020年1月14日 4 3 2分支程序设计 IF THEN结构 标号 条件满足 处理 N Y 程序结构 测试 比较指令 TEST CMP 条件转移指令 Jx标号 2020年1月14日 IF THEN ELSE结构 程序结构 TEST CMP指令Jx标号1处理体P1JMP标号2标号1 处理体P2标号2 其他指令 条件满足 处理P1 处理P2 标号1 标号2 条件1 条件2 2020年1月14日 标号1 条件1成立 P1 N Y CASE结构 程序结构 TEST CMP指令 测试条件1 Jx标号1 不满足转标号1处理体P1 JMP标号n 1标号1 TEST CMP指令 测试条件2 Jx标号2 不满足转标号2处理体P2 JMP标号n 1标号2 TEST CMP指令 测试条件3 Jx标号3 不满足转标号3处理体P3 JMP标号n 1标号3 TEST CMP指令 测试条件4 标号n 1 公共出口 条件2成立 条件n成立 Pn 1 标号2 标号n 标号n 1 P2 Pn N N Y Y 2020年1月14日 例4 7求补码数 X 补的绝对值 并送回原处 根据补码的定义 X 0 X 0 可得如下关系式 X 0 X 0 2020年1月14日 图4 7已知补码求绝对值的流程图 2020年1月14日 当X 0时 算式0 X 补实际上是对 X 补再求补 因而 可画出如图4 7所示的流程图 可以看出这是一个典型的IF THEN ELSE程序结构 程序清单如下 STACKSEGMENTSTACK DB10DUP 定义堆栈段 预留10个单元 STACKENDS DATASEGMENT XDW3456H 设 X 补 3456HDATAENDS 2020年1月14日 CODESEGMENT ASSUMECS CODE DS DATA SS STACK START MOVAX DATA 将数段段址送DS MOVDS AX MOVAX XADR 取 x 补到AX ANDAX AX 设置标志位 JNSDONE 若x 0 转DONE NEGAX 若 0 求补得到 x DONE MOVXADR AX 将 x 送回原处 MOVAH 4CHINT 21HCODEENDS ENDSTART 2020年1月14日 4 3 3循环程序设计 DO UNTIL结构 先执行 再判断条件 工作部分至少执行一次 初始化 循环体 循环控制 继续循环 Y N 2020年1月14日 DOWHILE结构 先判断条件 再执行 工作部分有可能一次都不执行 初始化 循环体 循环控制 继续循环 Y N 2020年1月14日 注意 循环可以嵌套 多重循环 但多个循环体之间不能交叉 控制条件不能混淆 2020年1月14日 例4 10设有一个首地址为ADDR的N字数组 试编写一个汇编语言程序 使该数组中的数按照从大到小的次序排列 数组排序问题通常采用气泡排序算法 具体过程如下 从数组的第一个数开始 依次对相邻两个数进行比较 若次序符合要求 则不进行任何操作 否则 将相比较的两数交换位置 第一遍比较 共进行了N 1次 完后 最小的数已放在数组的最后一个字的位置上 这样 进行第二遍比较时 只需对N 1个数进行考虑 即依次对相邻两数的比较操作只需进行N 2次 同理第三遍比较只需进行N 3次 总共最多进行N 1遍比较就可完成排序任务 976432 73 932 42 62 793462 973 43 63 974632 2020年1月14日 64 大小 数据从大到小排序 冒泡法 实例 内外两层循环 每轮内循环使一个最小的数沉底 因为最小的数沉底 下轮内循环就不用再比较最底下的数 所以内循环的循环次数每一轮比上一轮要逐次减1 外循环用于控制有多少轮内循环 若有n个数据 则外循环次数为n 1 程序清单如下 DSEGSEGMENT ADDRDWNDUP DSEGENDS CSEGSEGMENTASSUMECS CSEG DS DSEG START MOVAX DSEG MOVDS AX MOVCX N 内循环变量存于CX中 初值为N 1 DECCX LOOP1 MOVDI CX 外循环变量存于DI中 初值为N 1 MOVBX 0 地址指针预置为0 LOOP2 MOVAX ADDR BX 取相邻两数比较 CMPAX ADDR BX 2 JGECOTINUE 若符合排列次序 转移 XCHGAX ADDR BX 2 若不符合排列次序 二数交换 MOVADDR BX A 存大数 COTINUE ADDBX 2 修改地址指针 LOOPLOOP2 若一遍未比较完 继续 MOVCX DI LOOPLOOP1 若N 1遍未作完 继续 MOVAH 4CHINT21H MAINENDP CSEGENDS ENDSTART 2020年1月14日 4 3 4子程序设计 掌握以下几点 调用子程序用CALL指令 返回调用程序用RET指令子程序允许嵌套调用进入子程序后首先要保护主程序的运行状态 标志位 和使用的寄存器内容 称为保护现场 退出子程序前要恢复现场调用前要预先确定子程序中要使用哪些寄存器 并定义入口参数和出口参数 参数传递可利用寄存器 存储单元或堆栈 要用BP寻址 如前所述 过程的定义采用过程定义伪指令 格式ProcedurenamePROCattribute RET ProcedurenameENDP 过程名 Procedurename 是标识符 且写法与标号相同 调用过程时只要在CALL指令后写上该过程名即可 因而可以理解为过程名是子程序入口的符号地址 属性 attribute 字段用来指明过程的类型属性是NEAR 还是FAR RET指令总是放在过程体的末尾 用来返回主程序用 2020年1月14日 1 过程的定义和调用 2020年1月14日 过程的调用采用CALL指令 过程执行完毕返回主程序时 靠过程体最后RET指令的执行来保证 当一个过程和主程序在同一个代码段时 可采用段内调用方式 即过程具有NEAR属性 这时 CALL和RET指令执行时分别向堆栈压入和弹出一个字的偏移地址 即IP的内容 当一个过程和主程序不在同一代码段时 只能采用段间调用方式 即过程具有FAR属性 这时CALL和RET指令执行时分别向堆栈压入和弹出两个字 即段基值 CS内容 和偏移地址 IP内容 当过程和主程序在同一代码段时 过程定义和调用的格式如下 CSEGSEGMENT CALLSUBT SUBTPROCNEAR RET SUBTENDP CSEGENDS 例4 11 将前面顺序结构示例中用查表法将一位十六进制数转换成与其相对应的ASCII码 只考虑大写字母 的程序改为采用子程序结构来实现 要求调用该子程序不会影响主程序中的寄存器 2 寄存器内容的保护和恢复 通常主程序和过程的设计是分开进行的 因而它们所使用的寄存器往往会发生冲突 如果主程序中某寄存器的内容在调用过程后还要用 而被调用过程执行期间也要使用该寄存器 这样便会造成程序运行出错 为避免这类错误 应在进入过程时将该过程所用寄存器的内容保存起来 称为保护现场 而从过程返回主程序前 再将这些寄存器内容恢复 称为恢复现场 保护现场和恢复现场通常分别用堆栈压入指令和弹出指令来实现 3 主程序和子程序间的参数传送 主程序调用子程序时 必须先把子程序所需的初始数据 入口参数 设置好 子程序执行完毕返回主程序时也必须将过程运行所得的结果 出口参数 回送给主程序 子程序入口参数的送入和出口参数的送出称为主程序和子程序间的参数传送 常用的4种方法 1 用CPU内部的寄存器传送参数 用CPU内部的寄存器传送参数 意即过程的入口参数和出口参数均用寄存器传送 下边举例说明 2020年1月14日 例4 12编写一个过程 完成将4位十六进制ASCII码转换为等值二进制数 已知4位十六进制ASCII码存放在内存的某一区域中 且低位数的地址号低 而高位数的地址号高 将4位十六进制数ASCII码转换为等值二进制数的方法为 从最低位ASCII码开始 逐位将一个字节的ASCII码转换为等值二进制数 当数在0 9范围之内时 将其减30H 当其大于9时 将其减37H 入口参数 存放4位十六进制ASCII码的内存首地址ASC STG送入DS SI ASCII码的位数4存放在CL中 出口参数 转换结果 等值二进制数 存放在DX中 2020年1月14日 ASC BINPROCFAR PUSHAX 保护寄存器内容 MOVCH CL 位数送CH CLD 方向标志清零 XORAX AX AX及DX清零 MOVDX AX AGAIN LODSB DS SI AL SI 1 SI ANDAL 7FH 设置标志位 CMPAL 9 判该位ASCII码是否大于39H JGA TO F SUBAL 30H JMPSHORTROTATE A TO F SUBAL 37H ROTATE ORDL AL 拼装各位转换结果 RORDX CL DECCH JNZAGAIN POPAX RET ASC BINENDP 若有程序调用该子程序 已知数据段定义为 则参数传递及子程序调用程序可按如下格式编写 2020年1月14日 例4 13在某一程序中 若需对N个元素的数组求和 便可设计一个属性为NEAR的过程 它用来完成数组N个元素的求和 且过程和数组及主程序在同一代码段 这时主程序和过程如下 2 指定内存单元 变量 传递参数 2020年1月14日 2020年1月14日 2020年1月14日 3 通过地址表传送变量地址 仍以数组元素求和为例 可以看到该问题中有3个变量 与数组首元素地址连系的数组名 数组元素个数及累加和 每个变量都有它对应的偏移地址 它们的段地址均在DS寄存器中 把它们的偏移地址顺序存放在一张地址表中 该表长度为3个字 若需调用过程 应先将地址表的首地址送某寄存器 如BX 进入过程后可采用寄存器间接寻址方式从地址表中取出变量地址 以便访问所需变量 依此设计思想可有如下程序清单 DSEGSEGMENT ARY1DW100DUP COUNT1DW SUM1DW2DUP 2020年1月14日 2020年1月14日 2020年1月14日 PROADDPROCNEAR PUSHAX PUSHDX PUSHCX PUSHSI PUSHDI MOVSI BX 取数组地址 MOVDI BX 2 取元素个数 并送入CX MOVCX DI MOVDI BX 4 取和数地址 XORAX AX MOVDX AX 2020年1月14日 2020年1月14日 4 通过堆栈传送参数或参数地址 采用堆栈传送参数或参数地址的方法是 调用过程前在主程序中用PUSH指令将参数地址压入堆栈 进入过程后再用基址寄存器BP从堆栈中取出这些参数地址 并送寄存器 以便用寄存器间接寻址方式访问所需变量 仍以数组元素求和为例 程序清单如下 2020年1月14日 2020年1月14日 PROADDPROCNEAR PUSHBP MOVBP SP 采用BP访问参数地址 PUSHAX PUSHDX PUSHCX PUSHSI PUSHDI MOVSI BP 8 取数组地址 MOVDI BP 6 取计数值地址 MOVCX DI 计数值送CX MOVDI BX 4 和数地址送DI XORAX AX AX及DX清零 MOVDX AX 2020年1月14日 2020年1月14日 图6 10PROADD子程序执行时的堆栈内容 4 过程的嵌套 递归调用和可重入性 过程也可以作为调用程序去调用其它过程 称为过程的嵌套 一般来说 嵌套层次 也称嵌套深度 没有限制 只要堆栈空间允许即可 但当嵌套层次较多时应特别注意寄存器内容的保护和恢复 以免发生冲突 若使用堆栈传送参数 则必须十分小心地安排和处理堆栈操作 以保证程序正确执行 当子程序嵌套时 若某子程序要调用的子程序就是该子程序本身时 称为子程序的递归调用 能够进行递归调用的子程序称为递归子程序 或称递归过程 2020年1月14日 例6 14编写一个汇编语言程序 实现N N 0 N N N 1 N 2 1 可看出该例很适合用递归子程序的方法来实现 递归定义为 N N N 1 N 0 N 0 1N 0 求N 本身是一个子程序 由于N N N 1 求 N 1 必须调用求N 的子程序 但每次调用的入口参数和中间结果都不一样 2020年1月14日 图6 11计算N 的程序框图 2020年1月14日 DATASEGMENT 定义数据段 VAL NDW RESULTDW DATAENDS STACKSEGMENT 定义堆栈段 DW128DUP 0 TOPLABLEWORD STACKENDS CODE1PROCFAR ASSUMECS CODE1 DS DATA SS STACK 程序清单如下 2020年1月14日 START MOVAX STACK 设置SS及SP MOVSS AX MOVSP OFFSETTOP PUSHDS 将PSP中INT20H的首址压入堆栈 SUBAX AX PUSHAX MOVAX DATA MOVDS AX MOVBX OFFSETRESULT 将运算结果的地址压入栈 PUSHBX MOVBX VAL N 将参量N压入栈 PUSHBX CALLFARPTRFACT 递归调用FACT子程序 RET 2020年1月14日 MAINENDP CODE1ENDS CODESEGMENT FRAMESTRUC 定义结构数据模式 SAVE BPDW SAVE CS IPDW2DUP NDW RESULT ADDRDW FRAMEENDS ASSUMECS CODE 2020年1月14日 FACTPROCFAR PUSHBP 存BP MOVBP SP BP作为帧指针 PUSHBX 保护寄存器内容 PUSHAX MOVBX BP RESULT ADDR 结果地址送BX MOVAX BP N 取N CMPAX 0 N 0 JEDONE PUSHBX 下一次的结果地址入栈 DECAX N 1 压入栈 PUSHAX CALLFARPTRFACT MOVBX BP RESULT ADDR 结果地址送BX 2020年1月14日 MOVAX BX 上次的结果取入A MUL BP N AX N RESULT JMPSHORTRETURN DONE MOVAX 1 0 1 RETURN MOV BX AX 存最终结果 POPAX POPBX POPBP RET4 FACTENDP CODEENDS ENDSTART 2020年1月14日 图6 12求3 时的堆栈状态 2020年1月14日 5 常用子程序举例 1 两个多字二进制数加法子程序 子程序名 MW ADD 功能 完成两个多字二进制数加法 入口参数及其传送方法 数据段中的被加数 加数 它们的首地址分别存放在DS SI及DS DI中 被加数或加数的字数在CX中 出口参数及其传送方法 运算结果在内存中存放的首地址在DS BX中 所用的寄存器 该子程序返回调用程序后不改变任何寄存器原来的内容 2020年1月14日 程序清单如下 MW ADDPROCFAR PUSHAX 保护寄存器内容 CLC REPEAT MOVAX SI 取被加数的一个字 INCSI INCSI ADCAX DI 加上加数的相应字位 INCDI INCDI MOV BX AX 将一个字位的和存放内存 INCBX INCBX LOOPREPEAT 重复循环执行字加法运算 POPAX RET MW ADDENDP 2020年1月14日 若二个多字二进制数89376452H及47A632B1H要进行加法运算 则相应的调用程序如下 DATASEGMENT FIRSTDW6452H 8937H 定义被加数 SECONDDW32B1H 47A6H 定义加数 SUMDW2DUP 0 给结果预留4个单元 初值为0 ISIZEEQULENGTHSUM DATAENDS STACKSEGMENT DW100DUP TOPLABLEWORD STACKENDS CODESEGMENT ASSUMECS CODE DS DATA SS STACK 2020年1月14日 2020年1月14日 2020年1月14日 2 双字乘法子程序 双字 a1216 a0 乘双字 b1216 b0 的运算 乘积长度为4个字 其中a1 a0 b1 b0分别为对应于基数216 高位字 和20 低位字 的系数 2020年1月14日 据此 写出说明文件如下 子程序名 DWMULT 功能 完成双字乘双字的运算 入口参数及其传送方法 被乘数在内存中的首地址在DS SI中 乘数在内存中的首地址在DS DI中 出口参数及其传送方法 乘积在内存中的首地址在DS BX中 所用的寄存器 该子程序返回调用程序后不改变任何寄存器原来的内容 2020年1月14日 子程序清单如下 DWMULTPROCFAR PUSHAX PUSHDX MOVAX SI 取a0 MUL DI a0b0运算 MOV BX AX 存a0b0 MOV BX 2 DX MOVAX SI 2 取a1 MUL DI 计算 a1b0 MOV BX 4 DX a1b0的高位字暂存 ADD BX 2 AX a1b0的低位字加到a0b0高位字存储单元 2020年1月14日 ADC BX 4 0 向高位加进位 MOVAX SI 取a0 MUL DI 2 计算a0b1 并累加到相应存储单元 ADD BX 2 AX ADC BX 4 DX ADC BX 6 0 MOVAX SI 2 取a1 MUL DI 2 计算a1b1 ADD BX 4 AX ADC BX 6 DX POPDX POPAX RET DWMULTENDP 2020年1月14日 3 ASCII码十进制数乘法子程序 以一位ASCIIBCD码乘多位ASCIIBCD码为例 运算过
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 五年级上册劳动技术课工作计划
- 数字营销对消费者决策的影响
- 房地产金融行业市场现状及未来发展趋势展望
- 2025法律职业资格考试试题附答案详解
- 老酒店拆除施工方案
- 工程管理成本控制费用分析表
- 2025年铁路运营管理师新员工岗位专业知识笔试题目及答案
- 2024-2025学年全国统考教师资格考试《教育教学知识与能力(小学)》模考模拟试题含完整答案详解(各地真题)
- 2024年高升专检测卷含答案详解(研优卷)
- 户外运动安全承诺及免责合同
- 牙及牙槽外科
- 文物建筑保护修缮专项方案
- 万用表 钳形表 摇表的使用课件
- 63T折弯机使用说明书
- 营销与2008欧锦赛ktv渠道方案
- 170位真实有效投资人邮箱
- 工程力学ppt课件(完整版)
- 《区域经济学》讲义(1)课件
- 船模制作教程(课堂PPT)课件(PPT 85页)
- 化疗所致恶心呕吐护理
- 低碳生活我先行ppt
评论
0/150
提交评论