第4章 汇编语言程序设计 4.1 程序设计语言概述 4.2 汇编语言的程序结构与语句格式 4.3 汇编语言的伪指令 4.4 汇编语言程序设计方法 4.5 模块化程序设计技术 4.6 综合应用程序设计举例 4.7 汇编语言与C/C++语言的混合编程
第4章 汇编语言程序设计 程序:是一组为完成某种功能而按一定顺序(由算法确定) 汇编语言:具有执行速度快、易于实现对硬件控制等优点, 编排的指令序列。 汇编语言:具有执行速度快、易于实现对硬件控制等优点, 是实时控制等应用软件经常使用的程序设计语言。 本章重点:源程序基本结构 汇编语言的语法规则(基本语法及常用伪指令) 汇编语言程序设计方法 16位实模式程序设计。
4.1 程序设计语言概述 1. 3种语言 机器语言:当指令和数据都用二进制代码表示时,计算机 能够直接识别与执行,因而称之为机器语言。 第4章 汇编语言程序设计 4.1 程序设计语言概述 1. 3种语言 机器语言:当指令和数据都用二进制代码表示时,计算机 能够直接识别与执行,因而称之为机器语言。 高级语言:是完全独立于机器的通用语言,效率低。 面向过程、面向对象,必须译成机器语言。 汇编语言:是将机器指令符号化了的编程语言。 是一种采用助记符表示的、面向CPU指令系统的 程序设计语言。 机器语言程序 (目标代码) 高级语言源程序 编译或解释 (可由编译程序完成) 汇编语言源程序 汇编(可由汇编程序完成) 南京航空航天大学 电子信息工程学院
①能够利用硬件系统的特性(寄存器、标志、中断系统等) 直接对位/字节/字/寄存器/存储单元/I/O端口进行处理。 第4章 汇编语言程序设计 用汇编语言编写程序的优点: ①能够利用硬件系统的特性(寄存器、标志、中断系统等) 直接对位/字节/字/寄存器/存储单元/I/O端口进行处理。 ②采用CPU指令系统提供的各种寻址方式编制程序 目标代码占用内存少,执行速度快,效率高,具有实时性。 常用于编写系统软件、实时通信与控制程序、I/O接口驱动 等。 缺点:依赖于机器硬件,通用性和移植性较差。 2. 汇编程序(Assembler) (1)汇编程序的作用 ① 将源程序翻译成机器语言程序; ② 按用户要求自动分配存储区域(如程序区、数据区、堆栈区等); ③ 自动将各种进制 → 2#数;将字符 → ASCII码;计算表达式的值; ④自动对源程序进行检查,指出语法错误 (如,非法格式、未定义的助记符和标号、漏掉操作数等) 南京航空航天大学 电子信息工程学院
汇编程序提供汇编语言源程序的所有语法规则,常用的有 : ① ASM 基本汇编,占内存少; ② MASM 宏汇编,除ASM功能外,还支持: 第4章 汇编语言程序设计 (2)汇编程序分类 Microsoft公司 汇编程序提供汇编语言源程序的所有语法规则,常用的有 : ① ASM 基本汇编,占内存少; ② MASM 宏汇编,除ASM功能外,还支持: 宏操作、条件汇编、结构、记录等高级宏汇编语言功能。 有各种版本,并不断在升级中; TASM(Turbo Assembler) Borland公司的汇编编译器,性能同MASM。 ④ OPTASM(Optimizing Assembler) 一种优化的MASM 3. 汇编语言程序的上机与处理过程 南京航空航天大学 电子信息工程学院
应用软件 上机环境 用户开发的程序:ABC.exe等 操作系统:DOS系统 编辑器: EDIT.exe 编译程序:MASM.exe 第4章 汇编语言程序设计 上机环境 用户开发的程序:ABC.exe等 硬件 系统软件 应用软件 操作系统:DOS系统 编辑器: EDIT.exe 编译程序:MASM.exe 连接程序:LINK.exe 调试程序:DEBUG.exe CPU、存储器(ROM、RAM)、I/O接口、输入、输出设备 南京航空航天大学 电子信息工程学院
汇编语言上机过程 D:>EDIT ABC.ASM D:>MASM ABC 有语法错,回EDIT下修改程序 第4章 汇编语言程序设计 编辑源程序 EDIT ABC.ASM 汇编源程序 MASM 形成目标程序 ABC.OBJ 连接目标程序 LINK 有连接错误信息 ? 形成可执行程序 ABC.EXE 装入可执行程序到内存 , 并执行 D:\>sub>ABC 下一程序 用 DEBUG 调试可执行程序 D:\>sub> 找到原因 Y N 有汇编错误信息 运行结果正确 调试程序查错 汇编语言上机过程 D:>EDIT ABC.ASM D:>MASM ABC 有语法错,回EDIT下修改程序 D:>LINK ABC 有错,回EDIT下修改程序 D:>ABC 运行结果错,回EDIT下改程序 或在DEBUG下调试,找原因。 D:>DEBUG ABC.exe
源程序应按编译器(如,MASM汇编程序)能够理解的语法编写 第4章 汇编语言程序设计 4.2 汇编语言的程序结构与语句格式 语法:语句和程序结构必须遵循的规则 源程序应按编译器(如,MASM汇编程序)能够理解的语法编写 4.2.1 汇编语言源程序的框架结构 源程序的结构特点: 按逻辑段组织源程序。包括代码段、堆栈段、数据段等。 (1)源程序由若干个逻辑段组成 每段由伪指令SEGMENT开始,至ENDS结束(完整段定义)。 代码段:程序的主体(必不可少的段)。 堆栈段:在内存建立堆栈区,以存放中断或子程序调用时 的断点地址、各模块间传递的参数等。 数据段和附加数据段:在内存中建立适当容量的工作区, 以存放程序需要的常数或变量等。 程序中段的顺序:数据段、堆栈段定义在前,代码段在后。 (①变量应先定义;②汇编过程遇到变量时需要知道变量的属性)
源程序以END结束,它通知汇编程序停止汇编。 START标号为程序运行时的起始地址。 第4章 汇编语言程序设计 程序结构 (P133) ; ---------------------------------------------------------------------------------------- 段名1 SEGMENT ; 一个段的开始 语句1 语句2 …… 段名1 ENDS ; 一个段的结束 段名2 SEGMENT ; 另一个段的开始 段名2 ENDS ; 另一个段的结束 …… ; 其它段 END START ; 源代码结束 源程序以END结束,它通知汇编程序停止汇编。 START标号为程序运行时的起始地址。
每行只有一条语句且不能超过128个字符,允许有后续行。 第4章 汇编语言程序设计 程序中段的使用: 8086/8088/80286允许同时使用4种类型的段: 代码段 CS 、堆栈段 SS 、数据段 DS 和附加数据段 ES 80386/80486和Pentium系列允许同时使用6种段: 以上4个段 + FS和GS两个附加数据段 一个源程序中每种类型的段可不止使用一个,如:n个数据段。 在8086/8088和实地址模式下,每段的最大长度均为64KB; 在保护模式下,80286允许每个段的最大长度为16MB, 80386~Pentium系列CPU允许4GB。 (2) ASSUME伪指令 在代码段起始处用ASSUME伪指令说明各个段Reg与逻辑段 的关系,并在程序起始处设置段Reg的初值(代码段CS除外)。 (3)每段由若干语句行组成 每行只有一条语句且不能超过128个字符,允许有后续行。 END通知汇编程序停止汇编,START标号为程序运行时的起始地址。
(4)每条语句由4个字段构成。各字段间用空格分开。 第4章 汇编语言程序设计 (4)每条语句由4个字段构成。各字段间用空格分开。 (5)源程序中应设有返回DOS的指令语句,使程序执行完后能够 返回DOS系统的命令接受状态。 终止当前程序使其正确返回到DOS状态的常用方法有: ① 标准序法 将源程序中的主程序定义为FAR,其最后一条指令为RET; 在主程序的开始处使用3条指令: PUSH DS ;保存程序段前缀PSP的段地址 MOV AX,0 ;保存PSP的0偏移地址 PUSH AX ;注: 所保存地址中内容是INT 20H ② 使用DOS的4CH号功能调用 当程序执行到RET,这两个地址会弹出送IP、CS 不定义主程序为FAR过程并去掉上面3条指令; 在代码段结束(CODE ENDS)之前增加两条语句: MOV AH,4CH ;功能号4CH→AH INT 21H ;软中断调用 MASM从5.0版开始支持简化段定义,它通过伪指令EXIT返回DOS。
③ 表明:DS/ES在用户程序中应重新设置 第4章 汇编语言程序设计 源程序与PC DOS的接口 汇编语言源程序(.ASM)经过汇编转变为目标程序(.OBJ), 当用链接程序对其进行链接和定位时,操作系统为用户程序: ①建立1个256字节的程序段前缀区(PSP) INT 20H PSP起始0000H 定位用 户程序 PSP用于存放用户程序信息,包括: 在PSP的开始处(偏移地址0000H) 安排了一条INT 20H 软中断指令 INT 20H功能:系统返回到DOS管理状态 据此特征,用户编写程序时必须: 在程序执行完毕后,能够转到PSP起始处执行INT 20H指令。 ②定位用户程序 ③设置DS和ES的值,使之指向PSP的起始(DS/ES← PSP的段地址) ④以用户程序第1条指令的地址设置CS、IP;以堆栈段地址设置SS、SP。 ⑤运行用户程序 ③ 表明:DS/ES在用户程序中应重新设置
4.2.2 汇编语言的语句 1. 语句的种类与格式 (1)语句的种类 三种基本语句:指令语句、伪指令语句和宏指令语句 ① 指令语句 第4章 汇编语言程序设计 4.2.2 汇编语言的语句 语句:汇编语言源程序的基本组成单位,规定一个基本操作。 源程序:语句序列,完成某个特定的操作任务。 1. 语句的种类与格式 (1)语句的种类 三种基本语句:指令语句、伪指令语句和宏指令语句 ① 指令语句 ——可执行语句,对应CPU指令系统规定的一条指令。 汇编时,汇编程序为之产生一一对应的机器目标代码。 例:MOV DS,AX ;双字节指令,机器码为8EH、D8H ② 伪指令语句 ——由伪指令构成的说明语句(不可执行),可在任何段内。 汇编时,指示汇编程序如何汇编源程序,如分配存储单元、将程序分段等,本身不产生目标代码,CPU不执行。
例:SEGMENT/ENDS ; 将程序分段信息提供给汇编程序,以不同 第4章 汇编语言程序设计 例:SEGMENT/ENDS ; 将程序分段信息提供给汇编程序,以不同 ; 的名字来说明是数据段、代码段、堆栈段 例:MESSAGE DB ‘THIS IS A SAMPLE PROGRAM.’ ; 定义变量MESSAGE在数据段DATA中的存放形式 ;汇编时,汇编程序将MESSAGE定义为一个字节类 ;型数据区的首地址,并按字节存储字符串。 ③宏指令语句 ——是以某个宏名字定义的一段指令序列 汇编时,程序中有宏指令语句的地方被展开成相应的指令序列。宏指令语句是一般性指令语句的扩展。 例:SHIFT MACRO ;定义宏指令语句SHIFT MOV CL,4 SAL AL,CL ENDM 南京航空航天大学 电子信息工程学院
[标号:] [前缀] 指令助记符 [操作数] [;注释] 伪指令语句的格式: [名字] 伪指令定义符 [操作数] [;注释] 第4章 汇编语言程序设计 (2)语句的格式 [ ]表示可选 指令语句的一般格式: [标号:] [前缀] 指令助记符 [操作数] [;注释] 伪指令语句的格式: [名字] 伪指令定义符 [操作数] [;注释] ① 标号和名字 ——为指令单元和伪指令所起的符号名称,是自定义的标识符。 标号 后必须有冒号,代表指令所在存储单元的符号地址。 在程序中作为JMP、LOOP等指令的转移目标。 名字 用于定义常量、变量、过程、段名等,指示所定义变量、 过程以及段的起始地址。 命名必须符合汇编语言对标识符的规定: 以字母开头,由字母(不区分大小写)、数字(0~9)及部分特殊 字符(?@ $和下划线_等)组成的字符串,长度不超过31。 不能是有特定意义的保留字,如寄存器名AL和助记符等。
—— 规定指令或伪指令的操作功能,语句中唯一不可缺少的部分 第4章 汇编语言程序设计 ② 助记符、定义符 —— 规定指令或伪指令的操作功能,语句中唯一不可缺少的部分 指令助记符,汇编程序将其翻译成机器代码。 MOV AX,100H ;B8 00 01 伪指令定义符,汇编程序根据其要求的功能进行处理。 data SEGMENT ;data与某个段地址对应 string DB ‘Tsinghua’ ;定义string为字节存储区的起始地址 前缀仅可出现在指令助记符前(如,REP及段超越前缀等 ) ③ 操作数 指令语句中的操作数提供操作对象、存放位置、访问形式。 操作数可以是1个、2个或0个,2个时用逗号‘,’分开。 (INC BX; MOV AX,DATA ; RET) 伪指令语句中操作数的格式和含义随伪操作指令各有不同。 南京航空航天大学 电子信息工程学院
表达式操作数:如,[BX+2]、OFFSET NUM1 等。 第4章 汇编语言程序设计 操作数的表现形式有4种—— 常量操作数: 如 ,34 等。 寄存器操作数:如, AX 等。 存储器操作数:如,[0100H] 等。 表达式操作数:如,[BX+2]、OFFSET NUM1 等。 ④ 注释 ——以“ ;”开始,对程序的功能加以说明。 汇编程序对“ ;”之后的内容不做处理。 注释对汇编不起任何作用,不对应于任何机器码,仅增强 源程序的可读性。 南京航空航天大学 电子信息工程学院
——汇编时值已确定且程序运行期间不变化(立即数/端口地址) 第4章 汇编语言程序设计 2. 语句中的操作数(4种) (1)常量操作数 ——汇编时值已确定且程序运行期间不变化(立即数/端口地址) ①整型数值常量 用相应的后缀来定义:2#(B) 、10#(D)、8#(Q)、16#(H) 16#:必须以数字开头来区别H结尾的字符串(AH,abcdH) 即,最高位为字母‘A~F’时,必须加前缀 0。 ②字符串常量 用单引号括起来的一个或多个字符,值为每个字符的ASCII码值。 例: ‘2’=32H , ‘12’=3132H ,‘A’=41H , ‘AB’=4142H MOV AL,‘G’ ;AL← G的ASCII码值 ③符号常量 在程序中用标识符形式表示的常量,以提高程序的通用性。 (程序中,字符串常量与整型数值常量可交替使用) (2)寄存器操作数 ——操作数是寄存器名。如:AX、SI等,MOV AL,05。
① 标号:在代码段内 是指令所存放单元的符号地址。 第4章 汇编语言程序设计 (3)存贮器操作数 —— 地址型操作数,有标号与变量两种。 ① 标号:在代码段内 是指令所存放单元的符号地址。 ②变量:在数据段或堆栈段内 是以存储器寻址方式访问的操作数。 在程序中通过变量名(变量存储单元的符号地址)来引用。 ③标号和变量都与存储器地址相关联,应具有三种属性: 段属性(SEG):标号和变量对应存储单元的段地址,是段基 地址的高16位。 偏移量属性(OFFSET):标号和变量对应存储单元的偏移地址。 类型属性(TYPE): 对标号 指标号与使用它的指令之间的距离远近,有NEAR (近,段内转移或调用标号)和FAR(远,段间)。 对变量 指变量占用存取单元的字节数,有BYTE(字节)、 WORD(字)、DWORD(双字)、4字、10字节5种。
例:MOV AX,12–4 ; MOV AX,8 ;数值表达式 第4章 汇编语言程序设计 (4)表达式操作数 ——由各种操作数、运算符和操作符组成,在汇编时计算。 (不是在程序执行过程中)。 汇编程序先对表达式进行计算,再将得到的值汇编到指令中。 ① 数值表达式和地址表达式 数值表达式(汇编时产生一个数值): 由常量及算术逻辑运算符或关系运算符等连接而成。 地址表达式(值表示存储器地址,有上述三种属性): 由常量、变量、标号、寄存器及一些运算符组成。 例:MOV AX,12–4 ; MOV AX,8 ;数值表达式 LEA BX,[ string + 4 ] ;地址表达式 MOV BX ES:[SI + 4*3] ;地址表达式 南京航空航天大学 电子信息工程学院
MASM宏汇编中有三类运算符:算术、逻辑、关系运算符 两类操作符:分析、合成操作符 运算符:实现对操作数的相关运算。 第4章 汇编语言程序设计 ② 运算符和操作符 MASM宏汇编中有三类运算符:算术、逻辑、关系运算符 两类操作符:分析、合成操作符 运算符:实现对操作数的相关运算。 操作符:完成对操作数属性的定义、调用和修改。 主要有: 算术运算符 ( +、-、×、 / 、 MOD ) 逻辑运算符 ( AND、OR、NOT、XOR ) 关系运算符 ( EQ、NE、GT、GE、LT、LE ) 真:FFFFH 或 假: 0 分析操作符 ( SEG、OFFSET 、TYPE、SIZE、 LENGTH 、 HIGH、LOW ) 合成操作符 ( PTR 、DS:、THIS、SHORT) 南京航空航天大学 电子信息工程学院
算术运算符 ( +、-、×、/、MOD(取余数) ) MOV AX,6 × 8 ;MOV AX,48 第4章 汇编语言程序设计 算术运算符 ( +、-、×、/、MOD(取余数) ) MOV AX,6 × 8 ;MOV AX,48 ﹡数值表达式中可使用所有算术运算符 ﹡地址表达式仅可使用‘+、-’两种算术运算符 常用形式: 标号或变量±常量 运算结果仍为标号或变量,其三个属性中只有偏移量属性改变 例:设 PLACE是变量名,是个符号地址。则, PLACE+2×3仍是变量名,与PLACE的偏移地址之差为6 ﹡算术运算符不影响标志位 例:完成 80H + 90H 可以 MOV AL,80H+90H ;使用数值表达式 ;AL=10H、CF不变 或 MOV AL,80H ;使用加法指令 ADD AL,90H ;AL = 10H、CF = 1 南京航空航天大学 电子信息工程学院
逻辑运算符(AND、OR、XOR和NOT) ——实现操作数按位逻辑操作,只适用于数值表达式。 第4章 汇编语言程序设计 逻辑运算符(AND、OR、XOR和NOT) ——实现操作数按位逻辑操作,只适用于数值表达式。 MOV AX, 80h OR 70h ;MOV AX,0F0h 注意:逻辑运算符与逻辑指令助记符 形同意不同 ﹡作为助记符时,在程序运行时被执行,操作对象是reg/mem ﹡作为运算符时,在程序汇编时由汇编程序计算,计算结果 构成指令操作数的一部分 。 例:AND DX ,PORT AND 0FEH 汇编时产生一立即数,并得到 “ AND DX, imm ” 的目标码 CPU执行时完成 运算符 南京航空航天大学 电子信息工程学院
关系运算符(EQ、NE、LT、GT、LE和GE) 第4章 汇编语言程序设计 关系运算符(EQ、NE、LT、GT、LE和GE) ——在两个无符号操作数之间进行大小关系比较: 关系不成立(为假),则结果为“0”(假: 0); 关系成立(为真),则结果为全“1”(真:FFFFH)。 两个操作数必须同是数值 或 同一个段内的两个存储单元地址 结果值在汇编时获得 例:MOV BX,PORT LT 5 汇编为: MOV BX,0FFFFH(条件成立) 或: MOV BX,0000H (条件不成立) 分析操作符(数值返回运算符) ——运算对象是存储器操作数,它返回标号或变量的属性值。 合成操作符(修改属性运算符) ——作用于存储器操作数(标号或变量)时可以改变它们的属性。 南京航空航天大学 电子信息工程学院
③ 运算符和操作符的优先权等级 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 SHORT 11 OR,XOR 10 AND 第4章 汇编语言程序设计 ③ 运算符和操作符的优先权等级 SHORT 11 OR,XOR 10 AND 9 NOT 8 EQ,NE,LT,LE,GT,GE 7 +,-(双目) 6 *,/,MOD,SHL,SHR 5 +,-(单目) 4 HIGH,LOW (操作数高、低字节) 3 PTR,OFFSET,SEG,TYPE,THIS,段寄存名: (加段前缀) 2 LENGTH,SIZE,WIDTH,MASH,(),[ ],〈 〉 1 高 低 运 算 符 和 操 作 符 优 先 级 南京航空航天大学 电子信息工程学院
例:多个连续字节单元的累加 南京航空航天大学 电子信息工程学院 DATA SEGMENT ;定义数据段 第4章 汇编语言程序设计 例:多个连续字节单元的累加 段定义语句 DATA SEGMENT ;定义数据段 D1 DB 5 DUP(?) ;连续的字节单元 CC EQU $-D1 ;对单元计数 SUM DW 0 ;为结果保留一个字 DATA ENDS ;数据段定义结束 STACK SEGMENT PARA STACK ‘STACK’ ;定义堆栈段 DB 100 DUP (?) ;100字节的栈空间 STACK ENDS ;堆栈段定义结束 CODE SEGMENT ;定义代码段 ASSUME DS:DATA,SS:STACK,CS:CODE ;对各段进行说明 BEGIN:MOV AX,DATA ; DS初始化为DATA MOV DS,AX LEA SI,D1 ;预置源数据的指针 定义存储单元 的数据 伪指令 作堆栈用的存储单元 定义堆栈 指令 南京航空航天大学 电子信息工程学院
MOV CX,CC ;预置次数 南京航空航天大学 电子信息工程学院 LODS BYTE PTR [SI] ;取一个数并修改指针 第4章 汇编语言程序设计 MOV CX,CC ;预置次数 LODS BYTE PTR [SI] ;取一个数并修改指针 MOV AH,0 ;清AX的高字节 CLC ;清CF位 AGAN:ADC SUM,AX ;累加 LODS BYTE PTR [SI] ;再取数并修改指针 LOOP AGAN ;控制循环 MOV AH,4CH ;完成,返回DOS INT 21H CODE ENDS ;代码段结束 END BEGIN ;整个程序结束 段定义 汇编程序结束 南京航空航天大学 电子信息工程学院
4.3 汇编语言的伪指令语句 4.3.1 基本伪指令语句 ——指示汇编、链接程序如何进行汇编与链接。 影响目标代码生成,本身不产生目标代码。 第4章 汇编语言程序设计 4.3 汇编语言的伪指令语句 ——指示汇编、链接程序如何进行汇编与链接。 影响目标代码生成,本身不产生目标代码。 有 选择处理器方式、数据定义、程序分段、条件汇编、结构定义等 。 4.3.1 基本伪指令语句 符号定义、数据定义、程序分段、过程和宏定义、模块定义 等。 1. 符号定义伪指令 注:用EQU定义过的符号不能重新定义 ——给常量或表达式赋予一个符号名,方便在程序中的使用。 (1)等值语句EQU 符号名 EQU 表达式 例:PORT1 EQU 312 ;给常量赋予符号名 PORT2 EQU PORT1+1 ;给数值表达式赋予符号名PORT2 ADDR EQU ES:[SI+4] ;给地址表达式定义一个名字 CHAR EQU ‘NAME’ ;为字符串定义新的名字 COUNT EQU CX ;为CX定义新的符号名COUNT LD EQU MOV ;为MOV定义新的符号名LD
(2)等号语句= 符号名 = 表达式 (功能与EQU类似) 第4章 汇编语言程序设计 (2)等号语句= 符号名 = 表达式 (功能与EQU类似) 例: EMP=60 ;定义EMP等于60 EMP=EMP+1 ;重新定义EMP等于61 EMP=123*4 ;重新定义EMP等于492 EQU 与 = 的区别: 在同一源程序中,用EQU定义过的符号不能重新定义,= 可以。 例:B EQU [BP+8] B EQU 20H 不行! 特别注意: 符号定义是定义在程序中要使用的常量。 用EQU、= 定义的符号不占用存储器单元。 即,汇编程序不为这样的符号分配存储空间。 南京航空航天大学 电子信息工程学院
——用于定义变量(程序中所用的存储器操作数),指定 变量的类型和名称,为变量分配存储单元并赋初值。 第4章 汇编语言程序设计 2. 数据定义伪指令 ——用于定义变量(程序中所用的存储器操作数),指定 变量的类型和名称,为变量分配存储单元并赋初值。 (1)格式 [ ]表示可选 [变量名] 数据定义符 操作数 [,操作数]…[,操作数] 变量名 指示变量存储单元的符号地址 数据定义符 指示变量的类型(字节、字、双字等) 操作数 指示变量的内容(是赋给变量的初值) 多个相同类型的变量可在一条语句中定义 常用的数据定义符有: DB 定义字节变量,每个变量分配1字节的存储单元。 DW 定义字变量,每个变量分配2字节存储单元。 DD 定义双字变量,每个变量分配4字节存储单元。 南京航空航天大学 电子信息工程学院 存放时低对低高对高
其它的数据定义符有: DQ 变量为4字数据类型(64位) DT 变量为10字节数据类型(80位) 经过定义的变量有三种属性: 第4章 汇编语言程序设计 其它的数据定义符有: DQ 变量为4字数据类型(64位) DT 变量为10字节数据类型(80位) xx yy zz 01 FF FC 00 1 - 经过定义的变量有三种属性: SEGMENT,OFFSET, TYPE 段地址 可用操作符SEG获得 偏移量 可用操作符OFFSET获得 数据类型 可用操作符TYPE获得 例: 定义赋初值的变量 data SEGMENT xx DB 1, -1, 0fcH yy DW 1, -1, 0fcH zz DD 1, -1, 0fcH data ENDS
① 为数据项分配存储单元,用变量名作为该存储单元的名称。 第4章 汇编语言程序设计 (2)具体形式和功能 ① 为数据项分配存储单元,用变量名作为该存储单元的名称。 例:X DB 25H Y DW 4142H Z DD 12345678H X 12H 34H 56H 78H 41H 42H 25H Y Z 初始值也可以是表达式: IN_PORT DB PORT_VAL OUT_PORT DB PORT_VAL+1 PORT_VAL是符号常量,已由EQU语句赋了值。 PORT_VAL+1的值在汇编时计算 ② 预留内存单元,但不赋初值,以存放运算结果。 例: A DB ? ;操作数用‘?’表示 B DW ? 南京航空航天大学 电子信息工程学院
当表中的操作数相同时,可用DUP来缩写。 格式:重复次数 DUP ( 操作数) 第4章 汇编语言程序设计 ③ 定义一个表(数组) 例:W_TABLE DW 1122H,3344H B_TABLE DB 1,2,4,9,16 str1 str2 54 73 69 6e 67 48 75 61 49 4e 50 55 3a 0d 0a 24 ‘T’ ‘s’ ‘i’ ‘n’ ‘g’ ‘H’ ‘u’ ‘a’ ‘I’ ‘N’ ‘P’ ‘U’ ‘:’ 0dH 0aH ‘$’ 当表中的操作数相同时,可用DUP来缩写。 格式:重复次数 DUP ( 操作数) DUP是重复操作符 例:ALL_ZERO DB 0,0,0,0,0,0 ALL_ZERO DB 6 DUP(0) DUP还可以嵌套使用,P141 ④ 定义字符串(只能用DB定义 ) 例: str1 DB ' TsingHua ‘ str2 DB 'INPUT:' , 0dH , 0aH ,'$' 每个字符的值为它的ASCII码,所以只能用DB。 南京航空航天大学 电子信息工程学院
当字符串长度不超过两个字符时,也可以用DW来定义。 第4章 汇编语言程序设计 当字符串长度不超过两个字符时,也可以用DW来定义。 例:STRING1 DB ‘AB’ STRING2 DW ‘AB’ STRING3 DW ‘AB’,‘CD’ STRING1 STRING2 STRING3 43H 44H 41H 42H 注意:3个及以上的字符,只能用DB定义。 例: str1 DW ‘abcd’ str2 DD ‘abcd’ 南京航空航天大学 电子信息工程学院
例: 在DEBUG下查看变量存放情况。 第4章 汇编语言程序设计 data SEGMENT xx DB 1, -1, 0FCH 第4章 汇编语言程序设计 data SEGMENT xx DB 1, -1, 0FCH yy DW 1,- 1, 0FCH zz DD 1, -1, 0FCH str DB 'TsingHua' buf DB 4, ?,4 DUP (?) DB ‘dataend’ data ENDS code SEGMENT ASSUME CS:code ASSUME DS:data start: MOV AX , data MOV DS , AX LEA BX , xx LEA SI , yy LEA DI , zz MOV AH , 4CH INT 21H code ENDS END start 例: 在DEBUG下查看变量存放情况。
⑤ 当操作数是标号或变量时,可用DW或DD将标号或变量操作 数的偏移地址或全地址来初始化存储器。 第4章 汇编语言程序设计 ⑤ 当操作数是标号或变量时,可用DW或DD将标号或变量操作 数的偏移地址或全地址来初始化存储器。 例:XX DW CYCLE YY DD CYCLE … CYCLE: MOV BX,AX ;CYCLE是程序中一条指令语句的标号 TABLE SEG OFFSET 34H 12H TAL_PS 例:TABLE DB 12H,34H TAL_PS DD TABLE 例:VAR3 DW VAR+1 ; 将VAR+1的偏移地址存 入VAR3开始的两个字节 或 VAR3 DD VAR+1 ; 将VAR+1的全地址存入 VAR3开始的两个字 南京航空航天大学 电子信息工程学院
⑥ 数据定义语句使汇编程序对访问存储器的指令,产生正确的 目标代码。 第4章 汇编语言程序设计 ⑥ 数据定义语句使汇编程序对访问存储器的指令,产生正确的 目标代码。 例1:OPER1 DB ?,? OPER2 DW ?,? … MOV OPER1,0 ;字节0 → OPER1 MOV OPER2,0 ;字0 → OPER2 例2:SUM DB ? … INC SUM ;变量SUM的字节内容+1 例3:OPER1 DB 1,2 OPER2 DW 1234H,5678H … MOV AX,OPER1+1 MOV AL,OPER2 ;这里类型不匹配
用分析或合成操作符,可以返回或修改存储器操作数的三种属性。 第4章 汇编语言程序设计 (3)分析操作符与合成操作符 分析操作符(数值返回运算符) —— 运算对象是存储器操作数,它返回变量或标号的属性值。 合成操作符(修改属性运算符) ——作用于存储器操作数时可以改变它们的属性。 用分析或合成操作符,可以返回或修改存储器操作数的三种属性。 ① 分析操作符(SEG、OFFSET、TYPE、SIZE 、LENGTH) 使用格式: 操作符 标号或变量 SEG、OFFSET — 返回标号或变量的段地址和偏移地址 例:ARRAY DB 100 DUP(0) … MOV AX,SEG ARRAY MOV DS,AX ;对DS初始化 MOV BX,OFFSET ARRAY MOV AL,[BX] 南京航空航天大学 电子信息工程学院
TYPE — 返回存储器操作数(标号或变量)的类型值 其他情况返回1。 第4章 汇编语言程序设计 对变量:1/2/4 对标号:-1/-2 TYPE LENGTH SIZE TYPE — 返回存储器操作数(标号或变量)的类型值 LENGTH — 返回变量用DUP重复定义的的数据项总数, 其他情况返回1。 SIZE — 返回TYPE和LENGTH的乘积(为变量所分配的字节 单元总数) 例1:MOV AX,TYPE ARRAY ;ARRAY是字节变量,该语句汇编结果为 MOV AX,1 例2: 数据定义 LENGTH操作符 SIZE操作符 BUFFER1 DB 01H,02H LENGTH BUFFER1=1 SIZE BUFFER1=1×1=1 BUFFER2 DW 1234H LENGTH BUFFER2=1 SIZE BUFFER2=2×1=2 BUFFER3 DD 100 DUP(20H) LENGTH BUFFER3=100 SIZE BUFFER3=4×100=400 BUFFER4 DB ‘ABCD…Z’ LENGTH BUFFER4=1 SIZE BUFFER4=1×1=1
② 合成操作符 (PTR、LABLE、THIS) 第4章 汇编语言程序设计 ② 合成操作符 (PTR、LABLE、THIS) 仅在当前所在的指令中有效 PTR — 临时指定或修改存储器操作数的类型属性,保持原 有的段、偏移地址属性,且原定义的类型属性不变。 使用格式: 类型 PTR 标号或变量 类型有:BYTE、WORD、DWORD、NEAR、FAR等 对变量: 例:INC [BX] (有不确定性) INC BYTE PTR [BX] INC WORD PTR [BX] 例:ARRAY1 DB 0,1,2,3,4 ARRAY2 DW 0,1,2,3,4 MOV BX,WORD PTR ARRAY1[3] MOV CL, BYTE PTR ARRAY2[6] MOV WORD PTR[SI],4 南京航空航天大学 电子信息工程学院
配合EQU伪指令,可以为原变量定义新的变量名。 第4章 汇编语言程序设计 配合EQU伪指令,可以为原变量定义新的变量名。 ARRAY1 DB 0,1,2,3,4 ARRAY2 DW 0,1,2,3,4 WBYTE EQU WORD PTR ARRAY1 BWORD EQU BYTE PTR ARRAT2 MOV BX,WBYTE[3] ;按字使用 MOV CL, BWORD[6] ;按字节使用 对标号: 用PTR指明标号的类型时,可确定是段内转移或段间转移。 例:W_VAR DD INCHES … INCHES:CMP SUM,100 JMP WORD PTR W_VAR ;段内转移 或 JMP DWORD PTR W_VAR ;段间转移 或 JMP NEAR PTR INCHES ;段内转移 或 JMP FAR PTR INCHES ;段间转移 NEAR PTR可以略去
MOV AX,WORD PTR OPER1+1 ; AX=3402H 第4章 汇编语言程序设计 例:ABC DW ? A1 EQU BYTE PTR ABC ;A1是ABC的第一个字节 A2 EQU BYTE PTR ABC+1 或 A2 EQU A1+1 MOV AL,A1 MOV AH,A2 前例3: OPER1 DB 1,2 OPER2 DW 1234H,5678H … MOV AX,OPER1+1 MOV AL,OPER2 ;这里类型不匹配 对例3可如下处置: MOV AX,WORD PTR OPER1+1 ; AX=3402H MOV AL, BYTE PTR OPER2 ; AL=34H MOV AL, BYTE PTR OPER2+1 ; AL=12H
LABLE — 为当前存储单元定义一个指定类型的标号或变量。 第4章 汇编语言程序设计 LABLE — 为当前存储单元定义一个指定类型的标号或变量。 常用于定义1个数据块或标号, 使之具有多重名字和属性. 使用格式:标号或变量名 LABLE 类型 例:WBYTE LABLE WORD ;定义一个字类型的数据区 ARRAY DB 1,2,3,4 ;定义一个字节型的数据区 MOV AL,ARRAY ; 01H → AL MOV AX,WBYTE ;0201H → AX WBYTE 、ARRAY 指向同一个数据区,但有不同的类型属性 THIS — 与EQU配合使用,具有LABLE的同样作用。 使用格式: 标号或变量名 EQU THIS 类型 例:BWORD EQU THIS BYTE ; 定义字节 ARRAY DW 100 DUP(?) ;定义字 将原定义的字缓冲区ARRAY按字节区BWORD来使用 南京航空航天大学 电子信息工程学院
3. 程序分段伪指令(将程序分成若干逻辑段) ——用于告诉汇编程序和链接程序, 如何按逻辑段来组织程序和利用存储器。 具体来说 第4章 汇编语言程序设计 3. 程序分段伪指令(将程序分成若干逻辑段) ——用于告诉汇编程序和链接程序, 如何按逻辑段来组织程序和利用存储器。 具体来说 规定 段的起始和结束 指定 属性 开始地址边界 段类型 同名段的组合方式 有两种段定义 简化段定义:对MASM5.0以上版本 完整段定义:对所有版本 只介绍完整段定义 南京航空航天大学 电子信息工程学院
(1)段定义伪指令 SEGMENT/ENDS ——定义 DS/ES/SS/CS 段,指出段名和段的各种属性。 第4章 汇编语言程序设计 (1)段定义伪指令 SEGMENT/ENDS ——定义 DS/ES/SS/CS 段,指出段名和段的各种属性。 格式:段名 SEGMENT [定位类型][组合属性][‘类别名’] … (段体) 段名 ENDS 段的三个属性,顺序不可交换 段定义由伪操作SEGMENT开始、ENDS结束。SEGMENT/ENDS 必须成对出现,且段名(合法标识符)必须相同。 SEGMENT和ENDS语句之间可以有指令和其他伪指令,表示存放 在该段内存中的变量、指令或其他伪指令对该段内存的处理。 程序中可以定义多个段。 程序经汇编、链接及装入内存后,段名为一具体的段地址。 南京航空航天大学 电子信息工程学院 段起始地址的高16位
段的三个属性,为源程序的汇编与链接提供了必要的信息。 第4章 汇编语言程序设计 段的三个属性,为源程序的汇编与链接提供了必要的信息。 ①定位类型 — 告诉链接程序链接时段的起始边界。有4种选择。 定位类型 含 义 PARA(节) 段的起始地址必须为16的倍数(xxxx0H),缺省类型 PAGE(页) 段的起始地址必须为256的倍数(xxx00H),也就是页的起点上 WORD(字) 段的起始地址必须为偶数,它最适合于安排类型为字的数据段 BYTE(字节) 段可以从任意地址开始 ②组合类型 — 在多模块(每个模块有自己的代码段、数据段、 堆栈段)组合时,告诉链接程序本段与其他模 块中同名段的链接关系。有6种选择。 ③类别名 — 给各段的名字信息,用单引号括起来(‘STACK’、 ‘CODE’、‘DATA’等)。若缺省,表明该段类别为空。 同名同类别的段在内存中依序连续存放。
第4章 汇编语言程序设计 组合类型 含 义 NONE(默认状态) 本段与其他模块中的同名段无逻辑关系,各自有自己的段起始地址 PUBLIC 第4章 汇编语言程序设计 组合类型 含 义 NONE(默认状态) 本段与其他模块中的同名段无逻辑关系,各自有自己的段起始地址 PUBLIC 在满足定位类型的前提下,LINK程序将本段与其他模块中说明为PUBLIC的同名段邻接在一起,共用一个段地址,即合成一个物理段 STACK 是默认堆栈段需要指定的组合类型。LINK程序将所有堆栈段链接成一个连续段(长度是各堆栈段的长度之和),链接后自动初始化SS、SP。 如果在定义堆栈段时没有将其说明为STACK组合类型,需要在程序中用指令设置SS和SP的值,此时LINK程序会给出一个警告信息 COMMON 各模块中由COMMON方式说明的同名段重叠覆盖,有着相同的起始地址。段的长度取决于最长COMMON段的长度,段的内容为所链接的最后一个模块中COMMON段的内容以及没有覆盖到的前面COMMON段的内容 MEMORY 定位在所有链接在一起的其他段的最后(存储器高地址区域)。若有多个MEMORY段,汇编程序认为所遇到的第一个为MEMORY,其余为COMMON AT 表达式 定位在表达式的值所指定的段地址上。 如,AT 1930H,表示本段的起始地址为19300H
例: 两个模块,汇编连接后有—— 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 模块1: 第4章 汇编语言程序设计 例: 两个模块,汇编连接后有—— 模块1: STACK SEGMENT STACK DW 20 DUP (?) STACK ENDS DATA SEGMENT COMMON …… DATA ENDS CODE SEGMENT PUBLIC CODE ENDS END 模块2: STACK SEGMENT STACK DW 30 DUP (?) STACK ENDS DATA SEGMENT COMMON …… DATA ENDS CODE SEGMENT PUBLIC CODE ENDS END 南京航空航天大学 电子信息工程学院
汇编连接后,有: 设 模块2DATA > 模1DATA 模块2 DATA STACK 50个字 . 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 汇编连接后,有: . 模块1DATA 模块2代码 模块1代码 模块2 DATA 设 模块2DATA > 模1DATA STACK 50个字 南京航空航天大学 电子信息工程学院
——建立段与段寄存器之间的联系,说明源程序中定义 的段应由哪一个Sreg去寻址。 第4章 汇编语言程序设计 (2)段寄存器说明伪指令 ASSUME ——建立段与段寄存器之间的联系,说明源程序中定义 的段应由哪一个Sreg去寻址。 格式:ASSUME 段寄存器:段名[,段寄存器:段名,…] 注意: ASSUME并未真正的将段地址装入相应的Sreg Sreg(CS除外)的初值必须由用户在程序的开始处用指令来设置 例:P145 说明如下: ① 段定义时用了STACK,系统会自动初始化SS、SP,这时 可去掉SS:STACK以及代码段中初始化SS、SP的4条语句。 ② CS、IP的初始值由伪指令END MAIN装入,标号MAIN标示 程序开始执行的第1条指令地址, 只有主程序的END允许带标号。 基于① 、② ,通常在程序中仅需对DS、ES段寄存器作初始化。
——指示源程序到此结束(汇编程序不处理 END 之后的语句) 第4章 汇编语言程序设计 END伪指令(END 启动地址 ) ——指示源程序到此结束(汇编程序不处理 END 之后的语句) 注意: 源程序中必须有 END 结束语句。 启动地址可是一个标号或过程名, 指示程序的入口。 程序装入内存后,系统跳转到程序的入口处, 开始执行。 ③ 程序中 MOV BL,X MOV ALPHA,BL 因为ASSUME 的作用被汇编成: MOV BL,DS:X MOV ES: ALPHA,BL ④取消先前建立的段与段寄存器的联系 ASSUME 段寄存器: NOTHING 需要时可再重新建立段寄存器与新的段之间的关联。 南京航空航天大学 电子信息工程学院
——将程序中若干不同名的段集合成一个组,并指定组名。 格式:组名 GROUP 段名[,段名……] 第4章 汇编语言程序设计 (3)组定义伪指令 GROUP ——将程序中若干不同名的段集合成一个组,并指定组名。 格式:组名 GROUP 段名[,段名……] 组内各段装在一个64KB的物理段中,各段间的跳转是段内跳转。 记载正在汇编的指令代码或数据存放在当前段内偏移量的部件 (4)指定地址伪指令 ORG ——强行指定地址计数器LC的当前值,以改变段内在它 之后的代码或数据块存放的偏移地址。 格式1:ORG 表达式 ;将表达式的值(0~65535)→ LC 格式2:ORG $+表达式 ;将LC的当前值$+表达式的值→LC ORG语句之后段内所有的代码或数据均以表达式(常量) 的值为起始偏移量连续存放,除非遇到另一个ORG语句。 此语句本身并不占内存。 南京航空航天大学 电子信息工程学院
例1:设DATA的段地址为2000H DATA SEGMENT ORG 0004H AVR1 DW 2030H AVR2 DB 40H 第4章 汇编语言程序设计 例1:设DATA的段地址为2000H 00H 20H 06H 04H 40H 30H AVR1 AVR2 DWVR DDVR 0004H 0006H 0007H 0009H DATA SEGMENT ORG 0004H AVR1 DW 2030H AVR2 DB 40H DWVR DW AVR1 DDVR DD AVR2 DATA ENDS 南京航空航天大学 电子信息工程学院
例2: VECT SEGMENT ORG 10 VECT1 DW 47A5H ORG 20 VECT2 DW 0C956H 第4章 汇编语言程序设计 例2: VECT SEGMENT ORG 10 VECT1 DW 47A5H ORG 20 VECT2 DW 0C956H ORG $+8 (跳过8个字节的存储区) VECT3 DW 0123H 23H 01H … C9H 56H 47H A5H 10 20 16H+8=1EH 14H 1EH 15H 16H 南京航空航天大学 电子信息工程学院
例3:ARRAY DW 1,2,$+4,3, 4, $+4 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 0074H 01 第4章 汇编语言程序设计 例3:ARRAY DW 1,2,$+4,3, 4, $+4 0074H 0075H 76H 77H 78H 79H 7AH 7BH 7CH 7DH 7EH 00 82 04 03 7C 02 01 ARRAY 78H+4 ($+4) 7EH+4 ($+4) 南京航空航天大学 电子信息工程学院
例4: DATA SEGMENT ORG 30H DB1 DB 12H,34H ORG $+20H STRING1 DB ‘ABC … H’ 第4章 汇编语言程序设计 ‘H’ . 41H 34H 12H 30H 31H 20H COUNT STRING1 $→ 例4: DATA SEGMENT ORG 30H DB1 DB 12H,34H ORG $+20H STRING1 DB ‘ABC … H’ COUNT EQU $-STRING1 DATA ENDS 南京航空航天大学 电子信息工程学院
——过程(子程序)和宏都是程序段的一种形式,它们是 模块化程序设计的基础。 第4章 汇编语言程序设计 4. 过程和宏定义伪指令 ——过程(子程序)和宏都是程序段的一种形式,它们是 模块化程序设计的基础。 一段由CALL指令调用,用RET返回的程序 (1)过程定义伪指令 PROC/ENDP ——定义一个过程,并指出过程名及过程的属性。 格式:过程名 PROC [NEAR]/FAR … [RET] RET 过程名 ENDP 过程的属性,缺省时为NEAR 过程定义由PROC开始,至ENDP结束,之间为过程的指令序列。 程序中可以定义多个过程(主、子程序都可用过程来表示)。 程序经汇编、链接及装入内存后, 过程名为一具体的内存地址, 指示过程的入口。 南京航空航天大学 电子信息工程学院
NEAR过程只能被定义该过程的段中的其他程序调用(段内调用) 第4章 汇编语言程序设计 NEAR过程只能被定义该过程的段中的其他程序调用(段内调用) FAR过程可由任何段中的程序调用(段间调用) 根据过程的属性,汇编程序自动将CALL/RET指令翻译成段内 (段间)调用及段内(段间)返回的目标代码。 COD1 SEGMENT ASSUME CS: COD1, …… …… ; 代码段中的其它语句(主程序) SUB1 PROC FAR ; 名为SUB1的FAR过程开始 … RET ; 返回 SUB1 ENDP ; SUB1结束 SUB2 PROC ; 名为SUB2的NEAR过程开始 SUB2 ENDP ; SUB2结束 … ; 可能定义的其它过程 COD1 ENDS ; 代码段结束 南京航空航天大学 电子信息工程学院
使用“宏”功能可以减少重复编写相同语句段的工作。 宏功能的使用过程是:宏定义、宏调用、宏展开。 第4章 汇编语言程序设计 (2)宏定义伪指令MACRO/ENDM 使用“宏”功能可以减少重复编写相同语句段的工作。 宏功能的使用过程是:宏定义、宏调用、宏展开。 可同时包含指令语句和伪指令语句 ① 宏的定义、调用与扩展 宏定义格式:宏指令名 MACRO [形参,形参…] … ;宏体(指令序列) ENDM 宏定义是指用一个标识符(宏指令名)来代替一组指令序列 宏调用格式:宏指令名 [实参,实参…] 宏调用是在源程序中用宏指令代替所定义的程序段。 宏扩展:汇编时,将对应的宏体代替宏指令并产生目标代码。 宏体的每条语句前冠以“+” 。 例 P148 ② 取消宏指令名伪指令PURGE 格式:PURGE 宏指令名 [,…] ;注销之前定义的宏指令名
对需重复使用的模块既可定义为宏,也可定义为过程。 第4章 汇编语言程序设计 (3)宏与过程的区别 对需重复使用的模块既可定义为宏,也可定义为过程。 ①宏:由汇编程序识别,汇编时完成宏扩展(宏体代码插入)的处理。 过程:汇编时仅产生CALL指令的代码,在程序执行时完成调用。 ②宏可以直接传递参数,但过程传递参数的编程困难。 ③汇编成机器代码时, 宏扩展增加空间开销; 过程调用却缩短了机器代码的长度,无论过程被调用多少 次,仅增加CALL、RET的代码。 ④宏体执行时并不增加时间开销; 过程调用时,CALL、RET指令需保护/恢复现场和断点,增加 时间开销。 南京航空航天大学 电子信息工程学院
MASM提供了模块化编程伪指令,用以实现模块定义与通信。 第4章 汇编语言程序设计 5. 模块定义与通信伪指令 MASM提供了模块化编程伪指令,用以实现模块定义与通信。 一个任务的源程序由若干模块组成,每个模块有代码段、数 据段等,对应一个 .asm,是个独立的编译单位。 当各个模块编译完毕,用LINK连接各模块形成一个完整的可 执行程序(.exe)。 (1)模块定义伪指令 NAME/ END ——定义一个可以独立编写及汇编的程序模块 格式:[NAME 模块名] ;为模块命名 …… ;语句 END [标号] ;结束模块 表征程序启动地址 模块名的作用是指示给链接程序进行链接用。 模块命名语句NAME可以省略 ,此时源文件名为模块名。 主模块的END后要跟标号,子模块不跟标号。
(2)模块间通信伪指令 PUBLIC/EXTERN —— 实现模块间数据或过程的互访和共享 第4章 汇编语言程序设计 (2)模块间通信伪指令 PUBLIC/EXTERN —— 实现模块间数据或过程的互访和共享 格式:PUBLIC 名字 [,名字,…] EXTERN 名字:类型 [,名字:类型,…] 名字:标号、变量名、过程名、由EQU(或=)定义的符号名。 类型:BYTE/WORD/DWORD(变量)或NEAR/FAR(过程) 或ABS(常量属性)等 。 PUBLIC 和EXTERN配对使用; 由PUBLIC 说明的名字是全局的,可以在其他模块中使用; EXTERN表明本模块中使用的名字在别的模块中用PUBLIC 定义过,且类型一致。 南京航空航天大学 电子信息工程学院
—— 使汇编程序按照给定的条件对某部分源程序 汇编或不汇编。 第4章 汇编语言程序设计 6. 条件汇编伪指令 —— 使汇编程序按照给定的条件对某部分源程序 汇编或不汇编。 格式:IF 条件 ; 条件汇编开始 …… ; 语句体1 [ ELSE …… ] ; 语句体2 ENDIF ; 结束 有5种条件汇编伪指令,每种含2条相反条件的伪指令。 见P150。 南京航空航天大学 电子信息工程学院
(1)结构类型说明伪指令 STRUC/ENDS ——通知汇编程序增加了一个新的数据类型 第4章 汇编语言程序设计 7. 结构定义与使用伪指令 ——定义一些复杂的数据结构 结构定义与使用需要三个步骤: 结构类型说明→结构变量定义→结构引用 (1)结构类型说明伪指令 STRUC/ENDS ——通知汇编程序增加了一个新的数据类型 格式:结构名 STRUC ;MASM 6.1x后用STRUCT … ;结构体 结构名 ENDS 由数据定义语句序列组成 (2)结构变量的定义 ——为结构变量分配内存空间 格式: [结构变量名] 结构名 <[域值表]> 结构名同结构说明时的结构名; 域值表用于给结构变量的各域赋初值 。
—— 提供了访问结构变量或字段(成员变量 )的方法 第4章 汇编语言程序设计 (3)结构变量及其字段的引用 —— 提供了访问结构变量或字段(成员变量 )的方法 格式:结构变量名.结构字段名 ;“.” 是结构字段运算符 例:将一个学生的姓名、性别、学号、数学成绩、电路成绩 等定义为一个结构。 STUDENT STRUC ;由5个字段共9字节构成 SID DW ? ;学号 NAME DB 5 DUP(‘’) ; 预留5个字符空间 SEX DB ‘M’ ;性别 MATH DB 0 ;数学成绩 CIRCUIT DB 0 ;电路成绩 STUDENT ENDS 余见P151 变量本身还可以是另一个结构 南京航空航天大学 电子信息工程学院
4.3.2 80x86/Pentium CPU扩展伪指令 1. 处理器选择伪指令 ——告诉汇编程序当前CPU的工作方式和使用的指令集。 第4章 汇编语言程序设计 4.3.2 80x86/Pentium CPU扩展伪指令 1. 处理器选择伪指令 ——告诉汇编程序当前CPU的工作方式和使用的指令集。 省略时系统默认为8086/8088及8087指令集。 若想使用32位寄存器,须加上.386及以上CPU的选择伪指令。 伪指令 功 能 .286/.286C 选择80286非特权(实地址模式)指令和80287协处理器指令 .286P 选择全部80286指令和80287协处理器指令 .386/.386C 选择80386非特权指令和80387协处理器指令 .386P 选择全部80386指令和80387协处理器指令 .486/.486C 选择80486非特权指令 .486P 选择全部80486指令 .586/.586C 选择Pentium非特权指令 .586P 选择全部Pentium指令 .686/.686C 选择Pentium Pro~Pentium 4非特权指令 .686P 选择全部Pentium Pro~Pentium 4指令 .287 选择80287协处理器指令 .387 选择80387协处理器指令 .MMX 选择MMX指令 .XMM 选择SSE、SSE2、SSE3、SSE4指令
2. 80x86/Pentium CPU完整段定义的扩充伪指令 第4章 汇编语言程序设计 2. 80x86/Pentium CPU完整段定义的扩充伪指令 (1)完整段定义伪指令 SEGMENT/ENDS ——更好的表示32 位CPU的功能 格式:段名 SEGMENT [定位类型] [组合类型] [字长选择] [‘类别名’] … ;段体 段名 ENDS 省略时默认的段属性为USE32 字长选择: USEl6——16位段模式(对应实地址模式),字长为16位, 按16位方式寻址(段地址16位,偏移地址16位), 最大段长64KB。 USE32——32位段模式(对应保护模式),字长为32位, 按32位方式寻址(段选择子16位,偏移地址32位), 最大段长4GB。 注意见P152。 南京航空航天大学 电子信息工程学院
(2)80x86/Pentium汇编语言源程序结构 主要差异:① 增加了处理器选择; 第4章 汇编语言程序设计 (2)80x86/Pentium汇编语言源程序结构 主要差异:① 增加了处理器选择; ② 有字长选择可选项以确定段模式; ③ 允许同时使用CS、DS、SS及ES、FS和GS。 3. 存储模式定义伪指令 ——定义数据和代码的存放格式以及它们占用内存的大小。 格式:.MODEL 存储模式[,高级语言] 内存模式 说 明 TINY 微型模式 数据和代码放在同一个64KB段内,产生.com程序。MASM 6.x支持 SMALL 小模式 程序包含两个段:1个64KB代码段和1个64KB数据段(常用) MEDIUM 中模式 可以有多个代码段(1MB内),但是只有1个64KB数据段 COMPACT 紧凑模式 可以有多个数据段(1MB内),但是只有1个64KB代码段 LARGE 大模式 多个数据段(1MB内)与多个代码段(1MB内),但数据指针不能跨越64K段边界 HUGE 巨型模式 多个数据段(1MB内)与多个代码段(1MB内),数据指针可以跨越段边界 FLAT 平展模式 允许有1个512KB的段,用于存储代码和数据。MASM 6.0支持
——用来表示一个段的开始,同时说明前一个段的结束。 第4章 汇编语言程序设计 4.80x86/Pentium简化的段定义伪指令 ——用来表示一个段的开始,同时说明前一个段的结束。 若是程序中的最后一个段,则该段以END伪指令结束。 简化的段定义伪指令 格 式 功 能 段默认名 .CODE [段名] 定义代码段。如有多个代码段,要用段名区别 在TINY、SMALL、COMPACT及FLAT内存模式下,为 _TEXT .STACK [长度] 定义堆栈段,并形成SS、SP初值。SP=长度,若省略长度,SP=1024 为_STACK .DATA 定义数据段,要赋初值 为_DATA 例:P155 ①数据段名@DATA代表组所对应物理段的段地址。 ②汇编链接后,程序按代码段(默认PARA)、数据段(默认 WORD)、堆栈段(默认PARA)的顺序装入存储区。 南京航空航天大学 电子信息工程学院
使用简化段定义的程序框架 南京航空航天大学 电子信息工程学院 .MODEL SMALL ;定义存储模式 .386 ;定义处理器方式 第4章 汇编语言程序设计 如果.386放在.MODEL之前,段被定义成32位的段; 反之,是使用16位的段。 使用简化段定义的程序框架 .MODEL SMALL ;定义存储模式 .386 ;定义处理器方式 .STACK 64 ;定义堆栈段长度为64字节,并给SS、SP赋初值。 .DATA ;定义数据段 … .CODE ;定义代码段 .STRATUP ;程序开始,并初始化DS、SS、SP .EXIT 0 ;程序结束,返回DOS END ;整个程序结束,不必指定程序入口处的标号。 南京航空航天大学 电子信息工程学院
4.4 汇编语言程序设计方法 ——汇编语言程序的常用结构与设计方法 汇编语言源程序有顺序、分支、循环、子程序等基本结构形式 从组织结构看: 第4章 汇编语言程序设计 4.4 汇编语言程序设计方法 ——汇编语言程序的常用结构与设计方法 汇编语言源程序有顺序、分支、循环、子程序等基本结构形式 从组织结构看: 一个汇编语言源程序可由多个“模块”组成, 每个模块则由一个或多个“段”构成。 模块和段: 一个汇编“模块”可以包含一个或几个长度小于64KB的“段” 8086/8088允许同时使用4个段: 代码段(CS)、堆栈段(SS)、数据段(DS)和附加数据段(ES) 对应4个段寄存器(CS、DS、SS和ES) 使用汇编语言编程时需同时使用指令和伪指令 南京航空航天大学 电子信息工程学院
回顾例:多个连续字节单元的累加 南京航空航天大学 电子信息工程学院 DATA SEGMENT ;定义数据段 第4章 汇编语言程序设计 回顾例:多个连续字节单元的累加 段定义语句 DATA SEGMENT ;定义数据段 D1 DB 5 DUP(?) ;连续的字节单元 CC EQU $-D1 ;对单元计数 SUM DW 0 ;为结果保留一个字 DATA ENDS ;数据段定义结束 STACK SEGMENT PARA STACK ‘STACK’ ;定义堆栈段 DB 100 DUP (?) ;100字节的栈空间 STACK ENDS ;堆栈段定义结束 CODE SEGMENT ;定义代码段 ASSUME DS:DATA,SS:STACK,CS:CODE ;对各段进行说明 BEGIN:MOV AX,DATA ; DS初始化为DATA MOV DS,AX LEA SI,D1 ;预置源数据的指针 定义存储单元 的数据 伪指令 作堆栈用的存储单元 定义堆栈 指令 南京航空航天大学 电子信息工程学院
MOV CX,CC ;预置次数 南京航空航天大学 电子信息工程学院 LODS BYTE PTR [SI] ;取一个数并修改指针 第4章 汇编语言程序设计 MOV CX,CC ;预置次数 LODS BYTE PTR [SI] ;取一个数并修改指针 MOV AH,0 ;清AX的高字节 CLC ;清CF位 AGAN:ADC SUM,AX ;累加 LODS BYTE PTR [SI] ;再取数并修改指针 LOOP AGAN ;控制循环 MOV AH,4CH ;完成,返回DOS INT 21H CODE ENDS ;代码段结束 END BEGIN ;整个程序结束 段定义 汇编程序结束 南京航空航天大学 电子信息工程学院
4.4.1 程序设计的基本过程 程序设计的一般步骤: (1)分析问题并抽象出数学模型,确定最佳算法。 (2)画出程序结构框图和流程图。 第4章 汇编语言程序设计 4.4.1 程序设计的基本过程 程序设计的一般步骤: (1)分析问题并抽象出数学模型,确定最佳算法。 (2)画出程序结构框图和流程图。 (3)合理分配内存工作单元和寄存器,并了解I/O端口地址。 (4)编程并调试(静态或动态)。 (5)整理文档。贯穿程序设计的始终。 模块化设计方法 “自顶向下, 逐步细化” 结构化编码方法 顺序、分支、循 环三种基本结构 评价程序质量的标准: (1)合理组织数据,发挥MEM/Reg的作用。 (2)程序逻辑结构好,便于二次开发。 (3)可读性强。 (4)高可靠性和可维护性。 (5)效率高(代码少)。 南京航空航天大学 电子信息工程学院
第4章 汇编语言程序设计 汇编语言程序从编制到能够运行需要经过: 编辑、汇编、链接、调试 等。 南京航空航天大学 电子信息工程学院
——对应简单程序,顺序执行,无转移、无循环。 指令指针IP值线性增加。 分支结构 ——依据不同条件分支(双分支或多分支)到各程序段。 第4章 汇编语言程序设计 程序的基本结构 顺序结构 ——对应简单程序,顺序执行,无转移、无循环。 指令指针IP值线性增加。 分支结构 ——依据不同条件分支(双分支或多分支)到各程序段。 IP值受标志位的影响而跳变。 … Y N
循环结构 ——实现那些需要重复做的工作。 IP值因计数器CX中的值不为零而循环。 循环初始设置 循环初始设置 N 循环条件判断? 循环体 Y 第4章 汇编语言程序设计 循环结构 ——实现那些需要重复做的工作。 IP值因计数器CX中的值不为零而循环。 当型循环 (当条件成立进入循环) 循环初始设置 循环体 循环条件判断? Y N Y N 循环初始设置 循环体 循环条件判断? 直到型循环 (直到条件成立退出循环) 南京航空航天大学 电子信息工程学院
4.4.2 顺序结构程序设计 ——按事件发展的先后,选择合适的指令有序地加以组合。 第4章 汇编语言程序设计 4.4.2 顺序结构程序设计 PUSH DS SUB AX, AX PUSH AX MOV AX, DAT MOV DS, AX ——按事件发展的先后,选择合适的指令有序地加以组合。 例:编程计算表达式Z = X2-Y/5的值,其中X、Y为带符号字节整数,Z为带符号字整数。 MOV AL, X IMUL AL MOV BX, AX (BX)<= X*X (AX)<= Y/5 Z <=(BX)-(AX) 开 始 结束 MOV AL, Y CBW MOV CL, 5 IDIV CL SUB BX, AX MOV Z, BX RET 南京航空航天大学 电子信息工程学院
程 序 DAT SEGMENT X DB 10 DAT ENDS ASSUME DS: DAT, CS: COD COD SEGMENT 第4章 汇编语言程序设计 程 序 ;-- 数据段定义 ---------------------------------- DAT SEGMENT X DB 10 Y DB - 20 Z DW ? DAT ENDS ;-- 代码段定义 ---------------------------------- COD SEGMENT ASSUME DS: DAT, CS: COD MAIN PROC FAR PUSH DS ;标准序 SUB AX, AX PUSH AX MOV AX, DAT ;初始化DS MOV DS, AX 南京航空航天大学 电子信息工程学院
程 序(续) RET ; 过程结束,返回DOS 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 程 序(续) ;---------------------------------------------------------------------------- MOV AL, X IMUL AL MOV BX, AX ; BX <= X*X ;----------------------------------------------- MOV AL, Y CBW ; 将被除数扩展为字数据 MOV CL, 5 IDIV CL CBW ; AX <= Y/5 ;------------------------------------------------ SUB BX, AX MOV Z, BX ; Z <= BX-AX ;---------------------------------------------------- RET ; 过程结束,返回DOS MAIN ENDP COD ENDS END MAIN 南京航空航天大学 电子信息工程学院
例:将某段中的字符串“Hello!”传送到另一段中(内存数据块 的传送)。 第4章 汇编语言程序设计 例:将某段中的字符串“Hello!”传送到另一段中(内存数据块 的传送)。 利用变量定义字符串和缓冲区 开始 建立传送方向 DS: SI ← 源串首地址 ES: DI ←目的串首地址 CX 串长度 串传送 返回 DOS 南京航空航天大学 电子信息工程学院
aa SEGMENT ;数据段1 xx DB 'Hello!’ ;定义源串 aa ENDS bb SEGMENT ;数据段2 yy DB 6 dup (?) ; 定义目的缓冲区 bb ENDS cc SEGMENT ;代码段 ASSUME CS:cc, DS:aa, ES:bb ;指示指令中标号、变量所在段 start : CLD ;设置传送方向 MOV AX , aa ;DS: SI ← 源串首地址 MOV DS , AX LEA SI , xx MOV AX , SEG yy ;ES:DI ← 目的首地址 MOV ES , AX MOV DI , OFFSET yy MOV CX , 6 ;CX ← 串的长度 REP MOVSB ;串传送 MOV AH , 4CH ;调用4CH系统功能,返回DOS INT 21H cc ENDS END start ;指示程序结束和程序入口
南京航空航天大学 电子信息工程学院 D:\>EDIT hello.asm ;编写源程序 第4章 汇编语言程序设计 D:\>EDIT hello.asm ;编写源程序 D:\>MASM hello ; ;汇编源程序 Microsoft (R) Macro Assembler Version 5.10 Copyright (C) Microsoft Corp 1981, 1988. All rights reserved. 49860 + 421241 Bytes symbol space free 0 Warning Errors 0 Severe Errors D:\>LINK hello ; ;链接程序 Microsoft (R) Overlay Linker Version 3.61 Copyright (C) Microsoft Corp 1983-1987. All rights reserved. LINK : warning L4021: no stack segment D:\>hello ;执行程序 D:\> D:\>DEBUG hello.exe ;利用DEBUG查看结果 南京航空航天大学 电子信息工程学院
4.4.3 分支结构程序设计 设计分支程序的关键: 设定分支条件 分支结构的实现方法:①比较/测试 ;②跳转表分支 第4章 汇编语言程序设计 4.4.3 分支结构程序设计 设计分支程序的关键: 设定分支条件 分支结构的实现方法:①比较/测试 ;②跳转表分支 1. 比较/测试分支程序(适合于程序中仅有少数分支的情况) 方法:① 用比较指令CMP、或数据操作ADD/SUB/TEST等 指令来改变FR标志位OF/SF/ZF/PF/CF的值; ② 选用合适的条件转移指令Jcc,测试标志位的状态 来实现分支转移。 例:编程实现下列函数的功能,其中X、Y为无符号字节数。 南京航空航天大学 电子信息工程学院
流程图 AL = BL ? Y AL > BL ? N Y N AL <= X BL <= Y 开 始 Z <= 0 第4章 汇编语言程序设计 PUSH DS SUB AX, AX PUSH AX MOV AX, DAT MOV DS, AX 流程图 AL <= X BL <= Y 开 始 MOV AL, X MOV BL, Y CMP AL, BL JE C1 JA C2 AL = BL ? Z <= 0 Y C2: MOV AL, 1 JMP EXT AL > BL ? N Z <= 1 Y MOV AL, -1 Z <= -1 N 结 束 C1: MOV AL, 0 JMP EXT EXT: MOV Z, AL RET
程 序 南京航空航天大学 电子信息工程学院 ;-- 数据段定义 ---------------------------------- 第4章 汇编语言程序设计 程 序 ;-- 数据段定义 ---------------------------------- DAT SEGMENT X DB 242 Y DB 67 Z DB ? DAT ENDS ;-- 代码段定义 ---------------------------------- COD SEGMENT ASSUME DS: DAT, CS: COD MAIN PROC FAR PUSH DS ; 标准序 SUB AX, AX PUSH AX MOV AX, DAT MOV DS, AX ; 初始化DS 南京航空航天大学 电子信息工程学院
南京航空航天大学 电子信息工程学院 MOV BL, Y CMP AL, BL JE C1 ; AL=BL 则跳转至C1,否则继续执行 第4章 汇编语言程序设计 ;--------------------------------------------------------------------------------------- MOV AL, X MOV BL, Y CMP AL, BL JE C1 ; AL=BL 则跳转至C1,否则继续执行 JA C2 ; AL > BL 则跳转至C2,否则继续执行 MOV AL, -1 EXT: MOV Z, AL RET ; 返回DOS C1: MOV AL, 0 JMP EXT C2: MOV AL, 1 ;---------------------------------------------------------------------------------------- MAIN ENDP COD ENDS END MAIN 南京航空航天大学 电子信息工程学院
键盘输入与屏幕输出都是基于ASCII码的 第4章 汇编语言程序设计 例:将AL寄存器低4位2#以16#数形式显示在屏幕上。 键盘输入与屏幕输出都是基于ASCII码的 ① 需要 “2#数→16#数→ASCII码值”; ② “16#数→ASCII码值”时需判断: 16#数在0~9之间还是在A~F之间? AND AL,0FH ;取AL的低4位 ADD AL,30H ;16#数→ASCII码值 CMP AL,3AH JB PIT ;0~9,加上30H即为ASCII码 ADD AL,07H ;A~F,还需加上7为其ASCII码 PIT:MOV DL,AL ;DOS系统功能调用的2号子程序 MOV AH,02H ;显示单个字符 INT 21H 南京航空航天大学 电子信息工程学院
2. 利用跳转表实现分支(适合于多路分支的情况) 第4章 汇编语言程序设计 2. 利用跳转表实现分支(适合于多路分支的情况) 跳转地址(各分支程序入口地址) 跳转表的组成 跳转指令(转向分支程序的转移指令) 关键字 每条指令的目标代码长度一致 ①按一定的条件寻址到跳转表中相应的项; ②使用无条件转移指令JMP实现分支转移。 设计的关键 (1)根据表内地址分支 ——将各分支子程序入口地址顺序存放在内存区域,在主程 序中根据一定的算法计算出某子程序地址在跳转表中的 位置,进而得到相应子程序的入口地址,然后用JMP指令 转去执行。 A = ? 处理一 处理二 处理… 1 n 若是段内分支,每个地址在表内占2个单元(IP的值); 若是段间分支,每个地址占4个单元(CS:IP的值)。
各产品的加工子程序名分别为SBR0,SBR1,…,SBR7。编写由已知编号转至相应加工子程序处理的程序。 第4章 汇编语言程序设计 例:P158 设有8种产品的产品编号分别为0、1、2、…7, 各产品的加工子程序名分别为SBR0,SBR1,…,SBR7。编写由已知编号转至相应加工子程序处理的程序。 BASE JMP BASE[产品编号×2] ;段内间接转移 ; JMP mem IP ← [EA] ;EA=BASE+产品编号×2 ;[EA]=各子程序入口地址 子程序入口地址的地址 = 表基地址(BASE)+ 表内偏移量(产品编号)×2 南京航空航天大学 电子信息工程学院
南京航空航天大学 电子信息工程学院 DATA SEGMENT BASE DW SBR0,SBR1,SBR2,SBR3,SBR4, 第4章 汇编语言程序设计 DATA SEGMENT BASE DW SBR0,SBR1,SBR2,SBR3,SBR4, DW SBR5,SBR6,SBR7 ;定义跳转地址表 BN DB ? ;BN中存放某一产品编号 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ DB 100 DUP(0) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START PROC FAR PUSH DS MOV AX,0 PUSH AX 南京航空航天大学 电子信息工程学院
南京航空航天大学 电子信息工程学院 MOV AX,DATA MOV DS,AX MOV BL,BN ;取产品编号 第4章 汇编语言程序设计 MOV AX,DATA MOV DS,AX MOV BL,BN ;取产品编号 MOV BH,0 ;16位扩展 SHL BX,1 ;偏移量=产品编号×2 JMP BASE[BX] ;间接转移到相应的加工子程序 : SBR0: : RET SBR7: : START ENDP CODE ENDS END START BASE[BX]=[表基地址+编号×2] JMP mem 间接转移,IP ← [EA] 南京航空航天大学 电子信息工程学院
(2)根据表内指令分支(该表称为命令表,命令表存放在代码段。) ——将转移去各分支子程序的指令顺序存放在内存区域, 第4章 汇编语言程序设计 (2)根据表内指令分支(该表称为命令表,命令表存放在代码段。) ——将转移去各分支子程序的指令顺序存放在内存区域, 构成跳转表。若是段内转移,每条JMP是3字节指令。 只要能寻址到跳转表相应的项,即可执行转至某子程 序的JMP指令,实现程序的转移。 例:见上例 ① BX ← 表基地址+编号×3 ② JMP BX ;间接转移JMP reg ;IP ← BX,转移到BX 处 ③ 从[BX]中取出的是 JMP SBRi 指令,则转入子程序执行。 程序如下: 南京航空航天大学 电子信息工程学院
MOV AL,BN ;取产品编号 南京航空航天大学 电子信息工程学院 MOV AH,0 MOV BL,AL ADD AL,AL 第4章 汇编语言程序设计 MOV AL,BN ;取产品编号 MOV AH,0 MOV BL,AL ADD AL,AL ADD AL,BL ;偏移量=编号×3 MOV BX,OFFSET BASE ;取命令表基地址 ADD BX,AX ;求转移指令的地址 JMP BX ;间接转移到子程序 : BASE:JMP SBR0 ;命令表 JMP SBR1 : JMP SBR7 SBR0: : ;子程序0 SBR1: : SBR7: : ;子程序7 南京航空航天大学 电子信息工程学院
3. 用MASM 6.x伪指令设计分支程序(不作要求) 第4章 汇编语言程序设计 3. 用MASM 6.x伪指令设计分支程序(不作要求) MASM 6.X引入了.IF、.ELSE等条件控制伪指令,类似于 高级语言中分支语句的相应功能。 格式如下([ ]内的可选): .IF 条件表达式 ;条件为真,执行分支体 分支体 [.ELSEIF 条件表达式 ;IF条件为假且当前ELSEIF条件为真 ;执行分支体 分支体 ] [.ELSE ;前面IF[以及前面ELSEIF]条件为假 ;执行分支体 .ENDIF ;分支结束 南京航空航天大学 电子信息工程学院
循环程序是在满足某些条件时对一段程序的重复执行。 第4章 汇编语言程序设计 4.4.4 循环结构程序设计 循环程序是在满足某些条件时对一段程序的重复执行。 1. 循环程序的结构与循环控制方法 一般由4部分组成: (1)参数初始化 (2)工作部分 (3)参数修改 (4)循环控制 常用于循环次数未知时 常用于循环次数已知时 有“先执行,后判断”和“先判断,后执行”两种基本结构形式 南京航空航天大学 电子信息工程学院
例:统计字节数据块:-1,-3,5,6,9,…中负元素的个数。 第4章 汇编语言程序设计 先执行后判断(do—while) 例:统计字节数据块:-1,-3,5,6,9,…中负元素的个数。 .DATA BUF DB -1,-3,5,6,9,… ;定义若干字节带符号数 CUNT EQU $-BUF ;计算数据块长度 RESULT DW ? ;定义存放结果单元 .CODE .STARTUP MOV BX,OFFSET BUF ;建立数据指针 MOV CX,CUNT ;设置循环次数 MOV DX,0 ;置结果初值 LP1: MOV AL,[BX] ;取数据 AND AL,AL JNS PLUS ;是正数,转去PLUS INC DX ;是负数,负数个数+1 PLUS: INC BX ;调整数据指针 LOOP LP1 ;CX-1≠0,继续循环 MOV RESULT,DX ;存入负数个数 … 南京航空航天大学 电子信息工程学院
例:AX寄存器中有一个16位的二进制数,编程统计其中1的个 数,结果存放在CX寄存器中。 第4章 汇编语言程序设计 先判断后执行 例:AX寄存器中有一个16位的二进制数,编程统计其中1的个 数,结果存放在CX寄存器中。 控制循环体的条件:当AX内容为全0,不必再继续统计。 程序如下: MOV CX,0 ;置结果计数器初值 LP: AND AX,AX ;AX=0否 JZ EXIT1 ;是,退出循环 SAL AX,1 ;否,AX的最高位移至CF中 JNC ZERO ;CF=0,转ZERO继续循环 INC CX ;CF=1,结果计数器加1 ZERO: JMP LP EXIT1: : 南京航空航天大学 电子信息工程学院
常用循环控制方法: ① 计数控制——循环次数已知。 ② 条件/状态控制——循环次数未知。 南京航空航天大学 电子信息工程学院 方法二: 第4章 汇编语言程序设计 方法二: 每位和1“与”,不等0则为1。 MOV CX,16 MOV DX,0001H AA: TEST AX,DX JZ LOP : ;Di=1 LOP: SHR AX,1 LOOP AA 方法三: LOP: TEST AX,0FFFFH JZ STOP JNS SHIFT ;查SF INC CX SHIFT: SHL AX,1 JMP LOP STOP:HLT 常用循环控制方法: ① 计数控制——循环次数已知。 ② 条件/状态控制——循环次数未知。 南京航空航天大学 电子信息工程学院
2.多重循环程序设计 软件延时程序 南京航空航天大学 电子信息工程学院 SOFTDLY PROC 指令执行时间 MOV BL,10 4T 第4章 汇编语言程序设计 2.多重循环程序设计 软件延时程序 SOFTDLY PROC 指令执行时间 MOV BL,10 4T DELAY: MOV CX,2801 ;内循环延时 10ms 4T WAIT: LOOP WAIT 17T OR 5T DEC BL 3T JNZ DELAY 16T OR 4T RET 20T SOFTDLY ENDP 内循环 外循环 t={4+[10×(( 4+(2801×17-12))+3+16)-12]+20}×T 南京航空航天大学 电子信息工程学院
3. 用MASM6.X伪指令设计循环程序(不作要求) MASM6.X提供了循环控制伪指令用于设计循环程序, 可以简化编程,清晰结构。 第4章 汇编语言程序设计 3. 用MASM6.X伪指令设计循环程序(不作要求) MASM6.X提供了循环控制伪指令用于设计循环程序, 可以简化编程,清晰结构。 使用 .REPEAT和.UNTIL 使用 .WHILE和.EDNW .REPEAT ;重复执行循环体 … 循环体 .UNTIL 条件表达式 ;直到条件为真 .WHILE 条件表达式 ;条件为真, … 循环体 ;执行循环体 .EDNW ;循环体结束 使用 .REPEAT和.UNTILCXZ .REPEAT ;重复执行循环体 .UNTILCXZ [条件表达式] ;CX←CX-1直到CX=0 或 条件为真 例:P164 南京航空航天大学 电子信息工程学院
4.4.5 子程序设计与调用技术 合理使用子程序是实现模块化程序设计的重要方法。 两种子程序(过程): 1. 子程序的调用与返回 第4章 汇编语言程序设计 4.4.5 子程序设计与调用技术 合理使用子程序是实现模块化程序设计的重要方法。 两种子程序(过程): ① 重复使用的程序段或具有通用性便于共享的程序段 (键盘处理、代码转换等); ② 中断服务程序 (中断随机产生,对它的处理只能采用子程序的形式。) 1. 子程序的调用与返回 子程序在代码段中以过程的形式存在。调用方式有4种: 段内或段间的直接调用,段内或段间的间接调用。 对普通子程序 CALL:断点保护,转子程序。 RET: 断点恢复 。 对中断服务程序 INT指令或外部事件触发(段间的CALL ) IRET:断点恢复 。 南京航空航天大学 电子信息工程学院
“现场” — 转向子过程执行时主过程的状态,包括: 第4章 汇编语言程序设计 2. 子程序设计与应用中的问题 (1)现场的保护与恢复 “现场” — 转向子过程执行时主过程的状态,包括: 所有寄存器及指令指针的内容。 为避免主、子过程各自的数据信息与工作状态相互干扰, 程序设计时尽量使主、子过程有属于自己的工作空间。 形式一: DTOB PROC . PUSH BX . PUSH CX CALL DTOB . POP CX . POP BX . RET DTOB ENDP … 形式二: PUSH BX PUSH CX CALL 子程序 POP CX POP BX 常用方法:将PUSH与POP指令成对地安排在子程序的开始和结束 (对中断服务程序必须用这种方法)
入、出口参数:传给子程序的参数及从子程序返回的参数。 参数可以是数据本身,也可以是数据的存储地址。 第4章 汇编语言程序设计 (2)参数传递 入、出口参数:传给子程序的参数及从子程序返回的参数。 参数可以是数据本身,也可以是数据的存储地址。 参数传递常用方法(利用一些公共区域 ): ① 使用约定的寄存器传递; ② 使用约定的存储单元(参数表、变量)传递 ③ 使用堆栈传递 (3)子程序说明(对子程序的注释,方便调用者使用) ① 功能描述(子程序名称、功能、性能等)。 ② 入口、出口参数。 ③ 所用寄存器和存储单元。 ④ 子程序中又调用的其它子程序。 ⑤ 调用实例(可有可无)。 例:有一子程序说明如下。 ;子程序DTOB ;将两位10#(BCD码)转换成2# ;入口参数:AL存放10# ;出口参数:CL存放转换后的2# ;所用Reg:BX ;执行时间:0.06ms
(4)调用子程序的若干技术 ① 子程序嵌套调用:子程序中调用其它子程序称为嵌套。 只要堆栈空间允许,嵌套层次不限。 第4章 汇编语言程序设计 (4)调用子程序的若干技术 ① 子程序嵌套调用:子程序中调用其它子程序称为嵌套。 只要堆栈空间允许,嵌套层次不限。 ② 子程序递归调用:子程序直接或间接调用自身称为递归调用。 含有递归调用的子程序称为递归子程序。 ③ 可重入子程序:子程序被调用后,还未执行完又被另一个 程序调用的过程称为重入。 能够重入的子程序称为可重入子程序。 注:DOS功能调用是不可重入的。 主过程 子过程1 CALL 子过程1 断点1 子过程嵌套示意图 子过程2 ② ③ ④ ⑤ RET CALL 子过程2 断点2 ⑥ ⑦ ⑧ ⑨ ①
例1:求字节数组ARRAY中所有元素之和,结果送SUM字单元。 第4章 汇编语言程序设计 3. 子程序应用举例 (1)使用约定的寄存器传递参数。 方法:在主、子程序中使用相同的寄存器。 例1:求字节数组ARRAY中所有元素之和,结果送SUM字单元。 ;子程序名:SUM1。程序功能:求字节数组和 ;入口参数:SI=数组首址,CX=数组长度 ;出口参数:AX=数组和。 使用寄存器:AX,CX,SI SUM1 PROC NEAR CMP CX,0 JZ EXIT1 MOV AX,0 ;数组和在AX中 AGAIN: ADD AL,[SI] ADC AH,0 ;和或许为字 INC SI LOOP AGAIN EXIT1: RET SUM1 ENDP ;子程序(过程)结束
ARRAY DB d1,d2,d3,…,dn ;定义字节数组 第4章 汇编语言程序设计 DATA SEGMENT ARRAY DB d1,d2,d3,…,dn ;定义字节数组 COUNT EQU $-ARRAY ;若是字数组,个数=($-ARRAY) / 2 SUM DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX LEA SI,ARRAY ;入口参数准备,将需传递的参数送SI MOV CX,COUNT CALL SUM1 ;调用子程序求和,返回值在AX中 MOV SUM,AX ;和存于SUM单元 MOV AH,4CH ;返回DOS INT 21H … ;置SUM1于此,与主程序在同一代码段 CODE ENDS ;代码段结束 END START ;整个程序结束
将字数组的基地址、数组长度单元地址、和单元地址置于表中。 第4章 汇编语言程序设计 (2)使用约定的存储单元传递参数(方法有两种) ① 直接存储单元传递(又称变量传递) 利用约定的存储单元进行数据的传递,方法与寄存器传递类似。 ② 参数地址表传递 定义一个表存放待传参数的地址,将此地址表的首地址通过寄 存器传给子程序。子程序从地址表取得所需参数的地址,继而 取得参数。 例2:求字数组之和(假定和不溢出),结果送SUM字单元。 用‘参数地址表传递’ 法: 将字数组的基地址、数组长度单元地址、和单元地址置于表中。 ;子程序名:PRO_ADD。程序功能:求字数组和,并保存。 ;入口参数:BX为地址表首地址,参数地址在地址表中。 ;出口参数:和在SUM单元中。 ;使用寄存器:AX,CX,BP,SI,DI 南京航空航天大学 电子信息工程学院
ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX 第4章 汇编语言程序设计 … ;定义堆栈 DATA SEGMENT ARRAY DW d1,d2,d3,…,dn COUNT DW N SUM DW ? TABLE DW 3 DUP (?) ;定义地址表 DATA ENDS TABLE BX→ ARRAY 首地址 数组长度 单元地址 数组和 CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV TABLE,OFFSET ARRAY ;参数地址送地址表 MOV TABLE+2,OFFSET COUNT MOV TABLE+4,OFFSET SUM LEA BX,TABLE ;地址表首址→BX CALL PRO_ADD ;求和并存储 MOV AH,4CH INT 21H ;返回
南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 PRO_ADD PROC NEAR PUSH AX ;保护现场 … 第4章 汇编语言程序设计 PRO_ADD PROC NEAR PUSH AX ;保护现场 … MOV SI,[BX] ;数组首地址→SI MOV BP, [BX+2] ;数组长度单元地址→BP MOV CX,DS:[BP] ;数组长度→CX MOV DI,[BX+4] ;存储和单元地址→DI MOV AX,0 ADDIT: ADD AX,[SI] ADD SI,2 LOOP ADDIT ;循环求和 MOV [DI],AX ;存储和 POP AX ;恢复现场 RET PRO_ADD ENDP CODE ENDS END START 南京航空航天大学 电子信息工程学院
方法:将主、子程序需传递的参数压入堆栈,使用时从堆栈中取出。 第4章 汇编语言程序设计 (3)使用堆栈传递参数 方法:将主、子程序需传递的参数压入堆栈,使用时从堆栈中取出。 例3:改写例2为堆栈传参,并将求和子程序置于另一个代码段。 stack segment para stack ‘stack’ db 100 dup (?) stack ends data segment array dw d1,d2,d3,…,dn count dw n sum dw ? data ends extrn pro_add:far code1 segment assume cs:code1,ds:data start: mov ax,data mov ds,ax lea bx,array ;参数1进栈 push bx lea bx,count ;参数2进栈 push bx lea bx,sum ;参数3进栈 call far ptr pro_add ;段间调用 mov ah,4ch int 21h code1 ends end start ;主、子程序在两个不同的段中 子程序pro_add 实现求和
堆栈变换示意图如下: 南京航空航天大学 电子信息工程学院 第4章 汇编语言程序设计 参数1 参数2 参数3 CS IP AX BX CX 第4章 汇编语言程序设计 堆栈变换示意图如下: 参数1 参数2 参数3 CS IP AX BX CX BP 参数1 参数2 参数3 CS IP SP CALL 之前 之后 RET 6 现场保护 以后 现场恢复 起始地址 计数 和 南京航空航天大学 电子信息工程学院
pro_add proc far ;定义为far push ax ;保护ax push bx ;保护bx push cx ;保护cx 第4章 汇编语言程序设计 public pro_add code2 segment assume cs:code2 pro_add proc far ;定义为far push ax ;保护ax push bx ;保护bx push cx ;保护cx push bp ;保护bp mov bp,sp ;堆栈操作需要BP mov bx,[bp+14] ;取得地址参数 mov cx, [bx] mov bx,[bp+12] mov si, [bp+16] mov ax,0 addit: add ax,[si] ;求和 add si, 2 loop addit mov [bx],ax ;保存和 pop bp ;恢复现场bp 子程序名:PRO_ADD 功能:数组求和 入口参数:数组/数组长度/和单元 的地址在栈中 出口参数:和在SUM单元 使用寄存器:AX/BX/CX/BP/SI pop cx pop bx pop ax ret 6 pro_add endp code2 ends end ;返回并废除 地址参数
用户程序 ROM BIOS 基本I/O 系 统 硬 件 用户命令 第4章 汇编语言程序设计 4. 扩展的带参数过程定义伪指令(不作要求) 5. BIOS/DOS功能程序调用 用户程序 磁盘管理模块(DOS内核) MSDOS.SYS 系统功能 基本输入/输出 BIOS 模 块 IO.SYS 设备驱动 ROM BIOS 基本I/O 系 统 硬 件 装入 命令处理模块 COMMAN D.COM 用户命令 DOS系统层次结构
用户命令 用户程序 系 统 硬 件 南京航空航天大学 电子信息工程学院 层次特点: 命令处理模块 装入 第4章 汇编语言程序设计 第4章 汇编语言程序设计 层次特点: ROM BIOS中的子程序 使用IN/OUT指令直接控制外设, 实现与外设之间的输入/输出操作, 以软件形式向其上层提供服务。 IO.SYS中的子程序 ( 称基本输入/输出BIOS模块) 调用ROM BIOS的基本I/O功能, 向MSDOS.SYS提供设备驱动服务。 MSDOS.SYS中的子程序 ( 称DOS内核模块 ) 调用IO.SYS,实现对外设的控制。 与标准外设有两层隔离 : IO.SYS和ROM BIOS。 其中,21H类型的子程序 提供了丰富的系统服务,称21类型的调用为DOS系统(功能)调用。 用户程序 磁盘管理模块(DOS内核) MSDOS.SYS 系统功能 基本输入/输出 BIOS 模 块 IO.SYS 设备驱动 ROM BIOS 基本I/O 系 统 硬 件 装入 命令处理模块 COMMAN D.COM 用户命令 南京航空航天大学 电子信息工程学院
①尽可能使用DOS的系统功能调用,提高程序可移植性。 第4章 汇编语言程序设计 使用ROM BIOS和DOS系统 提供的功能模块程序,来完 成基本I/O操作,可以扩充汇 编语言的功能,方便程序编制。 用户程序 磁盘管理模块(DOS内核) MSDOS.SYS 系统功能 基本输入/输出 BIOS 模 块 IO.SYS 设备驱动 ROM BIOS 基本I/O 系 统 硬 件 装入 命令处理模块 COMMAN D.COM 用户命令 I/O操作的编程原则 ①尽可能使用DOS的系统功能调用,提高程序可移植性。 ②在DOS功能不能实现情况下,考虑用BIOS功能调用。 ③在DOS和BIOS的中断子程序不能解决问题时,使用IN/OUT指令直接控制硬件。 南京航空航天大学 电子信息工程学院
(1)调用BIOS/DOS功能程序的基本方法 第4章 汇编语言程序设计 (1)调用BIOS/DOS功能程序的基本方法 BIOS/DOS的每个功能程序都对应着一个子程序文件。 采用三步操作,配合一条软中断指令INT n 即可调用(中断调用): ① 依功能程序的要求,传送入口参数到指定寄存器; ② 将子功能编号(也称功能调用号)送AH寄存器; ③ 执行软中断指令INT n( n表征调用不同的功能程序(集) )。 BIOS中的n=5~1FH ,DOS中的n=20H/21H/23H~3FH DOS功能调用 类型码 中断功能 20H 程序结束 21H 请求DOS功能调用 22H 结束地址 23H 中止(Ctrl-Break)处理 24H 关键性错误处理 25H 磁盘顺序读 26H 磁盘顺序写 27H 程序结束且驻留内存 28H DOS内部使用 29~2EH DOS内部保留 2FH 30~3FH 南京航空航天大学 电子信息工程学院
与DOS相比,BIOS是在更低的层次上为用户提供系统服务 第4章 汇编语言程序设计 BIOS功能调用 类型码 中断功能 00 H 被零除 11 H 设备检测 01 H 单步 12 H 存储容量 02 H 不可屏蔽 13 H 磁盘I/O 03 H 断点 14 H 通信I/O 04 H 溢出 15 H 盒式磁带I/O 05 H 打印屏幕 16 H 键盘I/O 06 H 保留 17 H 打印机I/O 07 H 18 H ROM BASIC 08 H 日时钟 19 H 引导 09 H 键盘 1A H 0A H 1B H Ctrl-Break 0B H 串口2 1C H 定时器报时 0C H 串口1 1D H 显示器参数 0D H 硬盘 1E H 软盘参数 0E H 软盘 1F H 图形字符扩展 0F H 打印机 40 H 保留给软盘 10 H 显示器 41 H 硬盘参数 与DOS相比,BIOS是在更低的层次上为用户提供系统服务
使用BIOS的中断类型号10H、功能调用号0EH时: MOV AL,‘?’ ;要显示的字符送入AL 第4章 汇编语言程序设计 如,返回DOS的程序段 注意: 有的功能程序不需要入口参数, 则①可略去 ; 有的软中断号 n 对应一个分支程 序,调用时无需步骤中的② ; 序集,必须严格按三步流程顺序。 设置入口参数 在AH设置子功能号m 执行中断指令INT n 分析、应用出口参数 ① ② ③ 常用的有:INT 10H;INT 16H;INT 21H 例:将一个ASCII字符显示在屏幕当前光标位置。 使用BIOS的中断类型号10H、功能调用号0EH时: MOV AL,‘?’ ;要显示的字符送入AL MOV AH,0EH ;功能调用号送入AH INT 10H ;调用10H软中断 南京航空航天大学 电子信息工程学院 常用的BIOS与DOS功能调用说明参看附录B
(2)DOS功能程序与DOS系统功能调用 DOS系统功能调用— DOS功能调用在更高层次上提供了部分与BIOS类同的功能。 两者区别如下: 第4章 汇编语言程序设计 (2)DOS功能程序与DOS系统功能调用 DOS功能调用在更高层次上提供了部分与BIOS类同的功能。 两者区别如下: ① 调用BIOS功能程序比调用DOS的复杂一些,但运行速度快, 功能更强; ② DOS功能调用只适用于DOS环境,而BIOS功能调用不受任 何操作系统的约束; ③ 某些功能只有BIOS具有。 ① 单字符输入 ( 01H、07H功能 ) ② 显示单字符 ( 02H、05H 功能) ③ 单字符输入 或显示( 06H功能 ) ④ 字符串输入 ( 0AH功能 ) ⑤ 显示字符串 ( 09H 功能) ⑥ 检测键盘状态 ( 0BH功能 ) ⑦ 保存中断向量 ( 35H ) (见第6章) ⑧ 设置中断向量 ( 25H 功能) DOS系统功能调用— n= 2lH 的DOS功能程序调用 INT 2lH,对应100多个子功 能程序,体现了DOS的核心 功能。 常用的
①单字符输入 ( 01H、07H功能) 01H:入口参数 无 南京航空航天大学 电子信息工程学院 功能号 AH = 01H 类型号 21H 第4章 汇编语言程序设计 ①单字符输入 ( 01H、07H功能) 01H:入口参数 无 功能号 AH = 01H 类型号 21H 出口参数 AL = 键入字符的ASCII码 实现功能 等待从键盘输入一个字符, 并在屏幕上回显, 光标移动,检测Ctrl-Break键。 例 :利用键盘输入的字符产生程序分支。 MOV AH,1 ;等待从键盘输入 INT 21H CMP AL,‘Y’ ;是’Y’? JZ YES CMP AL, ‘y’ ;是’y’? NO: . . . JMP EXT YES: . . . EXT: . . . 南京航空航天大学 电子信息工程学院
INPUT: MOV AH, 07H ;等待从键盘输入 第4章 汇编语言程序设计 ①单字符输入 ( 01H、07H功能) 07H:入口参数 无 功能号 AH = 07H 类型号 21H 出口参数 AL = 键入字符的ASCII码 实现功能 等待从键盘输入一个字符, 不在屏幕上回显, 不检测Ctrl-Break键。 例:用不带回显功能输入密码。 INPUT: MOV AH, 07H ;等待从键盘输入 INT 21H MOV [DI], AL ;存入缓冲区 CMP AL, 0DH ;是回车符? JNZ INPUT ;不是,继续输入 CHECK: … … 南京航空航天大学 电子信息工程学院
02H:入口参数 DL = 要显示字符的ASCII 码 第4章 汇编语言程序设计 ②单字符输出显示( 02H、05H功能) 02H:入口参数 DL = 要显示字符的ASCII 码 功能号 AH = 02H 类型号 21H 出口参数 无 实现功能 显示指定字符,光标随动。 05H:将字符显示在打印机上。 例:显示字符A MOV DL, ‘A’ MOV AH, 02H INT 21H 例:使光标回到下一行的行首。 MOV DL , 0DH ;显示回车符 MOV AH , 02H MOV DL , 0AH ;显示换行符 南京航空航天大学 电子信息工程学院
③单字符输入或显示 ( 06H功能) 06H:入口参数 DL = 0FFH(输入) 例:P173 或 第4章 汇编语言程序设计 ③单字符输入或显示 ( 06H功能) 06H:入口参数 DL = 0FFH(输入) 或 DL≠0FFH(输出),其中是要显示字符的ASCII码 功能号 AH = 06H 类型号 21H 出口参数 若有输入(ZF=0),AL=输入字符; 否则(ZF=1),AL=0。 实现功能 输入单个字符或显示指定的字符。 例:P173 MOV DL,0FFH ;输入 MOV AH,6 INT 21H MOV DL,24H ;将‘$’输出 01H与06H的区别:前者等待用户键入,后者不等待用户键入。
④字符串输入 ( 0AH功能) 入口参数 DS : DX = 缓冲区的首地址 [DS : DX] = 限制最多输入的字符数 第4章 汇编语言程序设计 ④字符串输入 ( 0AH功能) 入口参数 DS : DX = 缓冲区的首地址 [DS : DX] = 限制最多输入的字符数 功能号 AH = 0AH 类型号 21H 出口参数 [DS : DX+1] = 实际键入的字符数(不含回车符) 从[DS : DX+2] 开始顺序存放键入的字符串, 回车符0DH为串尾最后一字符。 实现功能 等待从键盘输入字符串,并存入设定的缓冲区, 同时回显字符串,光标随着移动, 回车符使光标回到行首。 ASCII码 注意: 输入字符均带回显,光标随字符移动。输入回车符时光标回到行首。 回车符0DH作为一个输入的字符存放在字符串尾,但不计数。 实际最多能输入的字符数 = 限制的最多数-1 (回车符占1个) 执行完0AH功能后,DS和DX的值不变,仍指向缓冲区首地址。 应先定义缓冲区,再调用。缓冲区大小应为:限制的最多数 +2
例:用0AH功能输入字符串。 max DB 11 MOV CH, 0 data SEGMENT ;定义缓冲区 第4章 汇编语言程序设计 例:用0AH功能输入字符串。 data SEGMENT ;定义缓冲区 max DB 11 ;定义限制最多输入个数 DB ? ;用于存放实际输入个数 DB 11 DUP(?) ;用于存放输入的字符串 data ENDS code SEGMENT ASSUME CS:code, DS:data start: MOV AX, data ;置缓冲区地址于DS:DX MOV DS , AX LEA DX , max MOV AH , 0AH INT 21H ;调0A输入功能 MOV CH , 0 MOV CL , max+1 ;取字符串长度放CX LEA BX , max+2 ;取字符串首址于BX MOV AL , [BX] ;应用所输入的字符 … code ENDS max DB 11 lenth DB ? stri DB 11 DUP(?) MOV CH, 0 MOV CL, lenth LEA BX,stri
例:利用DEBUG查看0A功能输入结果。 data SEGMENT max DB 11, ?, 11 DUP(?) data ENDS 第4章 汇编语言程序设计 例:利用DEBUG查看0A功能输入结果。 data SEGMENT max DB 11, ?, 11 DUP(?) data ENDS code SEGMENT ASSUME CS:code, DS:data start: MOV AX, data ;置缓冲区地址于DS:DX MOV DS, AX LEA DX, max MOV AH, 0AH ;调输入功能 INT 21H MOV CH, 0 MOV CL, max+1 ;取输入长度到CX中 MOV AH, 4CH ;返回DOS code ENDS END start
D:\MASM>DEBUG TEST0a.exe ;装入执行文件 -U ;反汇编程序 第4章 汇编语言程序设计 D:\MASM>DEBUG TEST0a.exe ;装入执行文件 -U ;反汇编程序 129E:0000 B89D12 MOV AX , 129D 129E:0003 8ED8 MOV DS , AX 129E:0005 8D160000 LEA DX , [0000] 129E:0009 B40A MOV AH , 0A 129E:000B CD21 INT 21 129E:000D B500 MOV CH , 00 129E:000F 8A0E0100 MOV CL , [0001] 129E:0013 B44C MOV AH , 4C 129E:0015 CD21 INT 21 …… -D 129D:0 L10 ;查看程序执行前缓冲区内容 129D:0000 0B 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ -G 0000 ;执行程序 Hello ;从键盘输入字符串 Program terminated normally -D 129D:0 L10 ;查看程序执行后缓冲区内容 129D:0000 0B 05 48 65 6C 6C 6F 0D-00 00 00 00 00 00 00 00 ..Hello......... -
入口参数 定义要显示的字符串,字符串以’$’结束。 DS : DX = 字符串的首地址 功能号 AH = 09H 类型号 21H 第4章 汇编语言程序设计 ⑤字符串输出( 09H功能) 入口参数 定义要显示的字符串,字符串以’$’结束。 DS : DX = 字符串的首地址 功能号 AH = 09H 类型号 21H 出口参数 无 实现功能 显示字符串,遇 ’$’ 停止显示,光标随动。 南京航空航天大学 电子信息工程学院
例:编程显示字符串’ Tsinghua University’ 第4章 汇编语言程序设计 例:编程显示字符串’ Tsinghua University’ data SEGMENT ;定义显示的子符串 stri DB ‘Tsinghua University’, ‘$’ data ENDS code SEGMENT ASSUME CS:code, DS:data start: MOV AX, data ;置缓冲区地址于DS:DX MOV DS, AX LEA DX, stri MOV AH, 09H ;调显示功能 INT 21H MOV AH, 4CH ;返回DOS code ENDS END start 南京航空航天大学 电子信息工程学院
南京航空航天大学 电子信息工程学院 例:利用DOS系统功能调用实现人机对话。根据屏幕上显示 的提示信息,从键盘输入字符串并存入内存缓冲区。 第4章 汇编语言程序设计 (P173) 例:利用DOS系统功能调用实现人机对话。根据屏幕上显示 的提示信息,从键盘输入字符串并存入内存缓冲区。 DATA SEGMENT BUF DB 100 ;定义输入缓冲区长度 DB ? ;保留为填入实际输入的字符个数 DB 100 DUP(?) ;准备接收键盘输入信息 MESG DB ‘WHAT IS YOUR NAME ?$’ ;要显示的提示信息 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START:MOV AX,DATA MOV DS,AX … MOV DX,OFFSET MESG ;DS:DX指向MESG MOV AH,9 ;屏幕显示提示信息 INT 21H MOV DX,OFFSET BUF ;DS:DX指向BUF MOV AH,10 ;接收键盘输入 南京航空航天大学 电子信息工程学院
实现功能 检测键盘状态(通过检测键盘缓冲区实现) 第4章 汇编语言程序设计 ⑥检测键盘状态 ( 0BH功能) 入口参数 无 功能号 AH = 0BH 类型号 21H 出口参数 AL= FFH , 表示有键按下。 AL= 0 , 表示无键按下。 实现功能 检测键盘状态(通过检测键盘缓冲区实现) 例:利用0BH功能实现按键退出循环。 … Continue: … MOV AH, 0BH ;检测键盘缓冲区, 是否有键按下 INT 21H CMP AL, 0FFH JNZ continue ;无键按下继续循环 MOV AH, 4CH 南京航空航天大学 电子信息工程学院
4.5 模块化程序设计技术 4.5.1 模块化程序设计的特点与规范 良好的程序结构应该是模块化的 模块化程序设计—— 特点: 第4章 汇编语言程序设计 4.5 模块化程序设计技术 良好的程序结构应该是模块化的 4.5.1 模块化程序设计的特点与规范 模块化程序设计—— (1)将一个较大的‘任务’分解成N个具有独立功能的‘子任务’, 每个‘子任务’命名为一个模块并单独编辑(*.ASM); (2)对每个模块编译(MASM)后生成相应的.OBJ文件; (3)由LINK程序将各模块链接在一起,形成一个完整的可 执行程序(.EXE)。 特点: (1)大‘任务’分解成‘子任务’,缩短了程序设计周期; (2)对每个模块单独编写、调试 等,可以提高程序设计质量; (3)便于多种程序语言的联合使用; (4)模块程序可放在库里供多个程序使用。 南京航空航天大学 电子信息工程学院
4.5.2 程序中模块间的关系 1. 全局符号的定义与使用 (1)一个模块中定义的符号如不另加说明,均为局部符号。 第4章 汇编语言程序设计 模块化程序设计一般规范—— 模块的独立性要强且大小划分适中。 模块内部的聚合性要好。 每个模块最好只有一个入口和一个出口。 模块间的关系要明确。树型层次结构,各层间是单向依赖关系。 模块程序结构化:基本结构组合或嵌套,子程序的使用等。 4.5.2 程序中模块间的关系 1. 全局符号的定义与使用 (1)一个模块中定义的符号如不另加说明,均为局部符号。 局部符号只能在定义它的模块内使用。 (2)多个模块共用的符号必须是全局符号 在定义局部符号的模块中用PUBLIC语句说明, 在使用它的模块用EXTERN语句说明, 即可作为全局符号使用(局部符号 => 全局符号)。 南京航空航天大学 电子信息工程学院
通过指令:JMP、CALL或INT 实现,有近转移和远转移。 第4章 汇编语言程序设计 2. 模块间转移形式 通过指令:JMP、CALL或INT 实现,有近转移和远转移。 3. 多个模块的组合关系 各模块中的段有多种组合链接关系, 由段定义伪指令SEGMENT中的 “组合类型”属性来决定 。 组合类型 含 义 NONE (默认状态) 本段与其它模块中的同名段无逻辑关系,不组合,各自有自己的段起始地址。 PUBLIC 在满足定位类型的前提下,LINK程序将本段与其它模块中说明为PUBLIC的同名段邻接在一起,共用一个段地址,即合成一个物理段。 STACK LINK程序将所有堆栈段链接成一个连续段,组合后的物理段长度等于参与组合的各堆栈段的长度之和。 COMMON 各模块中由COMMON方式说明的同名段重叠履盖,有着相同的起始地址。重叠部分的内容取决于参与覆盖的最后一个段的内容,复合段的长度等于参与覆盖的最长的段的长度。 MEMORY 本段定位在所有链接在一起的其它段的最后(存储器高地址区域)。若有多个MEMORY段,汇编程序认为所遇到的第一个为MEMORY,其余为COMMON。
4.5.3 模块化程序设计举例 求无序表中的最大元素及其位置(在另一模块中实现)。 (1)算法 第4章 汇编语言程序设计 4.5.3 模块化程序设计举例 求无序表中的最大元素及其位置(在另一模块中实现)。 (1)算法 ① 先假设第1个数为最大值 , 则循环比较次数为 CX-1。 ② 再顺序与表后元素比较 ,将其中大的数取代当前的最大值。 MOV BX,OFFSET ARRAY MOV CX,COUNT MOV AL,[BX] ;设AL中是当前最大值 DEC CX ;比较CX-1次 INC BX AA: CMP AL,[BX] ;顺序与下一个元素比较 JGE NEXT ;前≧后,AL不变(带符号数比较) MOV AL,[BX] ;AL ←当前最大值 NEXT: INC BX LOOP AA … ;AL中即为最大值 设无序表中为带符号数
(2)用模块化设计方法 EXTERN FOUND:NEAR 南京航空航天大学 电子信息工程学院 将本程序分成两个模块来编写: 第4章 汇编语言程序设计 将本程序分成两个模块来编写: 模块A为主程序, 负责基本条件的设置。 模块B求最大值及其位置。 (2)用模块化设计方法 ;模块A,文件名MAIN.ASM EXTERN FOUND:NEAR DATA1 SEGMENT ARRAY DB d1,d2,d3,…,dn COUNT EQU $-ARRAY DATA1 ENDS CODE SEGMENT WORD PUBLIC ‘CODE’ ASSUME CS:CODE,DS:DATA1 MAIN: MOV AX,DATA1 MOV DS,AX ;装入段基址 MOV CX,COUNT LEA SI,ARRAY CALL FOUND MOV AH,4CH INT 21H CODE ENDS END MAIN 子程序FOUND求出最大值及其位置,在另一模块中。 南京航空航天大学 电子信息工程学院
;模块B,文件名SUB.ASM 第4章 汇编语言程序设计 PUBLIC FOUND AL:最大值 DL:最大值的位置 DH:待比较数据的位置 第4章 汇编语言程序设计 PUBLIC FOUND ;模块B,文件名SUB.ASM AL:最大值 DL:最大值的位置 DH:待比较数据的位置 DATA2 SEGMENT MAX DB ? PLACE DB ? DATA2 ENDS ;存最大值 ;存最大值 的位置 CODE SEGEMNT WORD PUBLIC ‘CODE’ ASSUME CS:CODE FOUND PROC NEAR MOV DH,1 MOV DL,0 MOV AL,[SI] DEC CX COMP: CMP AL,[SI+1] JG BIGGER MOV AL,[SI+1] MOV DL,DH BIGGER: INC SI INC DH 数据存在DATA2 LOOP COMP ASSUME DS:DATA2 MOV BX,DATA2 MOV DS,BX MOV MAX,AL MOV PLACE,DL RET FOUND ENDP CODE ENDS END 求最大值及其位置
注意: 南京航空航天大学 电子信息工程学院 (1)求最大值的算法。 (2)堆栈段(组合类型STACK)链接后是长度300字节的堆栈段; 第4章 汇编语言程序设计 注意: (1)求最大值的算法。 (2)堆栈段(组合类型STACK)链接后是长度300字节的堆栈段; 数据段(组合类型NONE)相互独立; 代码段组合成一个段(PUBLIC),为近(段内)调用。 (3)模块B中数据使用关系: ① 用模块A的数据(在模块B的开始处,无需设置DS); ② 求得的最大值结果存放在模块B的数据段(ASSUME)。 (4)对程序MAIN.ASM和SUB.ASM编译、链接的命令格式: D: > MASM MAIN ↙ D: > MASM SUB ↙ D: > LINK MAIN.OBJ+SUB.OBJ ↙ 则形成可执行文件MAIN.EXE。 南京航空航天大学 电子信息工程学院
只能使用8或16位寄存器,对内存寻址只能使用SI/DI/BX/BP。 第4章 汇编语言程序设计 4.6 综合应用程序设计举例 ——实模式程序设计、保护模式程序设计 实模式的默认条件下,MASM只接受8086/8088的16位指令集: 只能使用8或16位寄存器,对内存寻址只能使用SI/DI/BX/BP。 对80386及以上CPU来编写基于32位指令的实模式程序: ①用CPU选择伪指令来说明所使用的32位CPU; ②选择USE16或在选择伪指令之前加.MODEL来明确是实模式。 可使用8/16/32位寄存器,32位操作数,所有32位寄存器都可用 于内存寻址(按16位方式在1MB空间中寻址,分段最大64KB)。 Pentium MMX及以上CPU支持MMX、SSE~SSE4等多媒体指令: ① MMX指令集只能处理紧缩整型数据; ② SSE~SSE4指令集提供紧缩浮点型数据的并行处理能力。 保护模式和实模式以同样的方法使用和执行指令。 开机或复位时CPU总是进入实模式,实模式具有特权级0。 实模式与保护模式之间可以相互切换。
4.6.1 16位实模式程序设计(算术运算/代码转换/表的处理) 第4章 汇编语言程序设计 4.6.1 16位实模式程序设计(算术运算/代码转换/表的处理) 1. 算术运算 例1:多精度数加减(二进制数,低位在前) DATA SEGMENT X1 DW XXXXH,XXXXH X2 DW XXXXH,XXXXH X3 DW 0000H,0000H DATA ENDS STACK SEGMENT PARA STACK DW 20H DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN PROC FAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS ,AX CLC MOV CX,02H LEA SI, X1 LEA DI, X2 LEA BX,X3 E20: MOV AX,[SI] ADC AX,[DI] MOV [BX],AX ADD SI,2 ADD DI,2 ADD BX,2 LOOP E20 RET MAIN ENDP CODE ENDS END MAIN ADD会破坏CF,改用INC
例2(P177):多位非压缩的BCD数算术运算。 第4章 汇编语言程序设计 非压缩BCD 按字节运算 用AAA,AAS调整 压缩的BCD 用DAA,DAS调整 十进制数加减规律 例2(P177):多位非压缩的BCD数算术运算。 DATA SEGMENT FIRST DB 4, 7, 9, 2, 0 ;十进制数02974 SECOND DB 6, 2, 3, 7, 0 ;十进制数07326 THIRD DB 5 DUP(0) DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA UNPACK PROC FAR MOV AX,DATA MOV DS,AX ;DS指向数据段 MOV ES,AX ;ES指向数据段
南京航空航天大学 电子信息工程学院 LEA SI,FIRST LEA BX,SECOND LEA DI,THIRD MOV CX,4+1 第4章 汇编语言程序设计 LEA SI,FIRST LEA BX,SECOND LEA DI,THIRD MOV CX,4+1 CLD RETRY: LODSB ADD AL,[BX] AAA STOSB INC BX ADC BYTE PTR[BX],0 LOOP RETRY MOV AH,4CH INT 21H UNPACK ENDP CODE ENDS END UNPACK 循环初始化 CLC CLD RETRY: LODSB ADC AL,[BX] AAA STOSB INC BX LOOP RETRY 或: ;将[SI] → AL且SI+1→ SI ;对应的一位进行加法运算 ;保存当前和 ;进位值加到加数的下一位 南京航空航天大学 电子信息工程学院
BCD ←→2# 2. 代码转换 16# ←→ ASCII BCD ←→ ASCII 例1(P178):压缩BCD数转换为二进制数 第4章 汇编语言程序设计 几种主要代码间的转换 BCD ←→2# 16# ←→ ASCII BCD ←→ ASCII 2. 代码转换 例1(P178):压缩BCD数转换为二进制数 算法:各位权×各位的值,再相加。 二进制数值 =(千位×1000)+(百位×100)+(十位×10)+个位 ={[(万位×10+千位)×10+百位]×10+十位}×10+个位 MOV BX,AX ;保存BCD码到BX MOV AX,0 ;结果单元清零 MOV CX,4 ;共处理4位BCD数 RETRY: PUSH CX MOV CL,4 ROL BX,CL ;高位BCD数→BX的低字节 POP CX MUL W10 ;AX×10 →DX:AX PUSH BX AND BX,000FH ;取出1位BCD数 ADD AX,BX POP BX LOOP RETRY 某位×10+下一位
例2(P178):二进制数转化为BCD码(设AX中的值<10000) 第4章 汇编语言程序设计 例2(P178):二进制数转化为BCD码(设AX中的值<10000) 算法1:先除以最高位权值,商为该位的BCD数,余数继续 除以次权值,依次下去。 W1000 DW 1000, 100, 10, 1 ;定义千, 百, 十, 个位的权值 ;子程序名:AX2TOBCD。 ;入口参数:AX = 二进制数。 ;出口参数:AX = 压缩BCD码。 算法2:连续除以10取余。 首先将AX中的数除以10,所得余数为个位上的BCD数; 所得的商再作为被除数来除以10,得到的余数为十位上 的BCD数,…,直到被除数小于10时,得到最高位的 BCD数。 南京航空航天大学 电子信息工程学院
南京航空航天大学 电子信息工程学院 ATOBCD PROC ;算法1 … ;保护现场 XOR BX,BX ;BCD码暂存单元BX清零 第4章 汇编语言程序设计 ATOBCD PROC ;算法1 … ;保护现场 XOR BX,BX ;BCD码暂存单元BX清零 MOV SI,OFFSET W1000 ;权值首地址送SI MOV CX,4 ;循环次数4→CX RETRY: PUSH CX MOV CL,4 SHL BX,CL ;BX初值为0 MOV DX,0 ;DX:AX组成被除数 DIV WORD PTR [SI] ;除以权值,商、余数→ AX、DX OR BX,AX ;压缩BCD码 MOV AX,DX ;余数送AX POP CX ADD SI,2 ;地址加2,指向下一权值 LOOP RETRY MOV AX,BX ;BCD码由BX→AX … ;恢复现场 RET ATOBCD ENDP 除以权值,商为该位的BCD数 南京航空航天大学 电子信息工程学院
例3:将BX寄存器中的2#用16 #的形式显示在屏幕上。 第4章 汇编语言程序设计 例3:将BX寄存器中的2#用16 #的形式显示在屏幕上。 ① 2# →16# (每4位一组) ② 16# →ASCII 并显示:0~9 +30H; A~F +37H 算法:将4位2# 数+30H后做一次判断: 若原字符在‘0’~‘9’之间,输出; 若原字符‘A’~’F’之间,应再加7(即+37H)输出。 循环4次 MOV CH,4 ROTATE: MOV CL,4 ROL BX,CL MOV AL,BL AND AL,0FH ADD AL,30H CMP AL,3AH ; > 9? JL PRINTIT ADD AL,7H PRINTIT: MOV DL,AL MOV AH,2 INT 21H DEC CH JNZ ROTATE RET BH BL 显示 每次从高位16#开始转换 南京航空航天大学 电子信息工程学院
3. 表的处理和应用 顺序查找法(无序,有序) 折半查找法(有序) 查找 在表中插入字符或字符串 求表中的最大与最小元素 无序表中的元素排序 第4章 汇编语言程序设计 3. 表的处理和应用 顺序查找法(无序,有序) 折半查找法(有序) 查找 在表中插入字符或字符串 求表中的最大与最小元素 无序表中的元素排序 例1(P180):在字节数组中找出第一个非零元素,并显示它的下标。 . MODEL SMALL . DATA ARRAY DB 0,0,0,25H,0,0,34H,36H,45H COUNT EQU 9 . CODE START: MOV AX,@DATA MOV DS,AX MOV CX,COUNT MOV DI,-1 ;DI为元素下标
南京航空航天大学 电子信息工程学院 NEXT: INC DI ; 从0号元素起,逐个与0比较 CMP ARRAY[DI],0 第4章 汇编语言程序设计 NEXT: INC DI ; 从0号元素起,逐个与0比较 CMP ARRAY[DI],0 LOOPZ NEXT JNE OK ;ZF=0,即有非零元素,转OK MOV DL,‘0’ ;没有找到非零元素,显示一个‘0’ JMP SHOW OK: MOV DX,DI OR DL,30H ;将下标转换成ASCII码 SHOW: MOV AH,02H INT 21H ;显示下标 MOV AX,4C00H ;返回DOS INT 21H . STACK END START 南京航空航天大学 电子信息工程学院
冒泡排序:从前至后,两两比较,逆序则交换。 一趟排序可以将最大(或最小)的沉下去。 第二趟依次进行,可以将次大(次小)的 沉下去。 … 第4章 汇编语言程序设计 例2(P180):冒泡法给无序表中的元素排序。 冒泡排序:从前至后,两两比较,逆序则交换。 一趟排序可以将最大(或最小)的沉下去。 第二趟依次进行,可以将次大(次小)的 沉下去。 … 若有n个元素,则内循环n-1次,外循环n-1次 ,是个双重循环。 特别:在表已几乎排序的情况下,外循环可不做到n-1次,就提 前结束程序,这必须以内循环是否交换了元素为前提, 若无交换,说明已排好序。 设置一个标志 FLAG= -1 无序 0 有序 初始,设FLAG = -1,无序表,进入外循环一次; 重设FLAG = 0,进入内循环后,若有交换,置FLAG为-1。 回到外循环起始处,检查FLAG。
第4章 汇编语言程序设计 开 始 N Y Y N 结束 Y N MOV BX, COUNT MOV AX, DATA MOV DS, AX 第4章 汇编语言程序设计 外循环初始化:预置外循环次数 开 始 MOV BX, COUNT MOV AX, DATA MOV DS, AX LP1: CMP FLAG,0 JE EXIT Y 内循环初始化:置内循环次数 置数组的偏移地址SI;预置交换标志为0 N 检查是否进入内循环 DEC BX MOV CX,BX MOV SI,0 MOV FLAG,0 LP2: MOV AX, ARRAY[SI] CMP AX, ARRAY[SI+2] 取一个字ARRAY[SI]进AX 与 下一个字ARRAY[SI+2]比较 XCHG AX,ARRAY[SI+2] MOV ARRAY[SI], AX MOV FLAG,-1 JLE NEXT 逆序交换,置交换标志为-1 N AX <= ARRAY[SI+2]? Y EXIT: RET NEXT: ADD SI, 2 LOOP LP2 JMP LP1 内循环条件判断: CX =0? Y N 内循环地址SI+2,内循环次数CX-1 结束
程序如下: DATA SEGMENT ARRAY DW d1,d2,d3,…,dn COUNT EQU ($-ARRAY)/2 ;数据个数 第4章 汇编语言程序设计 程序如下: DATA SEGMENT ARRAY DW d1,d2,d3,…,dn COUNT EQU ($-ARRAY)/2 ;数据个数 FLAG DB -1 ;交换标志,初值为-1 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ DB 1024 DUP(?) STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA SORT: MOV AX,DATA MOV DS,AX MOV BX,COUNT LP1: CMP FLAG,0 ;数组已有序? JE EXIT ;是,排序结束
LP2: MOV AX,ARRAY[SI] ;取一个数据→AX CMP AX,ARRAY[SI+2] ;与下一个数比较 第4章 汇编语言程序设计 DEC BX ;否,置本遍扫描比较次数 MOV CX,BX MOV SI,0 ;置数组的偏移地址 MOV FLAG,0 ;预置交换标志为0 LP2: MOV AX,ARRAY[SI] ;取一个数据→AX CMP AX,ARRAY[SI+2] ;与下一个数比较 JLE NEXT ;后一个数大,转NEXT XCHG AX,ARRAY[SI+2] ;逆序,交换两个数 MOV ARRAY[SI],AX MOV FLAG,-1 ;置交换标志为-1 NEXT:ADD SI, 2 ;修改地址指针 LOOP LP2 ;循环进行两两数据的比较 JMP LP1 ;内循环结束,继续下一遍排序 EXIT: MOV AH,4CH ;排序完成,返回DOS INT 21H CODE ENDS END SORT
4.6.2 基于32位指令的实模式程序设计 针对386及以上CPU来编写基于32位指令的实模式程序: 第4章 汇编语言程序设计 4.6.2 基于32位指令的实模式程序设计 针对386及以上CPU来编写基于32位指令的实模式程序: 用CPU选择伪指令来说明所使用的32位CPU; 选择USE16段模式(完整段定义) 或 在CPU选择伪指令之前加以.MODEL(简化段定义); 可使用所有的8位、16位和32位寄存器,32位操作数; 所有32位寄存器都可用于内存寻址 (在1MB内存空间中寻址,分段最大64KB)。 例(P182):冒泡排序。 余课堂不作要求。 南京航空航天大学 电子信息工程学院