920 likes | 1.12k Views
第 4 章 汇编语言程序设计. 汇编语言用指令 助记符 来表示操作码和操作数,用符号地址表示操作数地址,给程序编写带来了很大方便。 用汇编语言编写程序的主要 优点 是程序设计人员可以直接对硬件编程,程序效率高,执行速度快,目标代码短,占用存储空间少。. 4.1 汇编语言的基本语法. 4.1.1 汇编程序的建立过程. (1) 用编辑程序建立 .ASM 源文件; (2) 用汇编程序把 .ASM 文件转汇编成 .OBJ 文件; (3) 用链接程序把 .OBJ 文件连接成 .EXE 文件;
E N D
第4章 汇编语言程序设计 汇编语言用指令助记符来表示操作码和操作数,用符号地址表示操作数地址,给程序编写带来了很大方便。 用汇编语言编写程序的主要优点是程序设计人员可以直接对硬件编程,程序效率高,执行速度快,目标代码短,占用存储空间少。
4.1 汇编语言的基本语法 4.1.1汇编程序的建立过程 • (1) 用编辑程序建立 .ASM源文件; • (2) 用汇编程序把 .ASM文件转汇编成 .OBJ文件; • (3) 用链接程序把 .OBJ文件连接成.EXE文件; • (4) 用DOS命令直接键入文件名就可执行该程序。 • 常用的汇编程序有Microsoft公司推出的宏汇编程MASM和BORLAND公司推出的TASM。我们采用QASM2.7版。
4.1.1汇编程序的建立过程 • 为运行汇编语言程序,至少要在磁盘上提供以下文件: • (1) 编辑程序,如EDIT.EXE; • (2) 汇编程序,如MASM.EXE; • (3) 连接程序,如LINK.EXE; • (4) 调试程序,如DEBUG.COM。
4.1.2 汇编语言程序格式 【例】将变量VAR1和VAR2相减,并将结果送入变量RESULT。 DATA SEGMENT ;定义数据段 VAR1 DW 7654H ;定义变量VAR1初值为7654H VAR2 DW 2345H ;定义变量VAR2初值为2345H RESULT DW ? ;定义变量RESULT DATA ENDS ;数据段结束 CODE SEGMENT ;定义代码段 ASSUME CS: CODE , DS: DATA ;为各个逻辑段指定段寄存器
4.1.2 汇编语言程序格式 START: MOV AX, DATA ;初始化数据段寄存器DS MOV DS, AX MOV AX, VAR1 ;变量VAR1送AX SUB AX, VAR2 ;AX-VAR2结果送AX MOV RESULT, AX ;结果送变量RESULT MOV AH, 4CH ;调用4CH号DOS中断 INT 21H ;返回操作系统 CODE ENDS ;代码段结束 END START ;汇编结束
4.1.2 汇编语言程序格式 物理地址是由段地址和偏移地址组合而成的,汇编程序在把源程序转换为目标程序时,必须确定标号和变量(代码段和数据段的符号地址)的偏移地址,并且需要把有关信息通过目标模块传送给连接程序,以便连接程序把不同的段和模块连接在一起,形成一个可执行程序。为此,需要用段定义伪操作。
4.1.2 汇编语言程序格式 • SEGMENT_NAME SEGMENT • SEGMENT_NAME ENDS • 其中,删节号部分对于数据段、附加段和堆栈段来说,一般是存储单元的定义、分配等伪操作;对于代码段则是指令及伪操作。 …
4.1.2 汇编语言程序格式 • 还必须明确段和段寄存器的关系,可用ASSUME伪操作来实现,其格式为 • ASSUME <段寄存器名>:段名,... • ASSUME <段寄存器名>:NOTHING • 其中,段寄存器名必须是CS、DS、ES和SS中的一个,而段名则必须是由SEGMENT定义的段中的段名。ASSUME NOTHING则可取消前面由ASSUME所指定的段寄存器。
较为完整的汇编源程序段定义。 • DATE_SEG1 SEGMENT;定义数据段 • DATE_SEG1 ENDS • DATA_SEG2 SEGMENT;定义数据附加段 • DATA_SEG2 ENDS • CODE_SEG SEGMENT;定义代码段 • ASSUME CS:CODE_SEG,DS:DATA_SEG1,ES:DATA_SEG2 • START: ;开始执行的入口地址 … … 4.1.2 汇编语言程序格式
4.1.2 汇编语言程序格式 ;设置DS寄存器为当前数据段 MOV AX,DATA_SEG1;将数据段地址赋予DS MOV DS,AX ;设置ES寄存器为当前附加段 MOV AX,DATA_SEG2;将附加数据段地址赋予ES MOV ES,AX CODE_SEG ENDS ;代码段定义结束 END START;源程序结束 …
4.1.2 汇编语言程序格式 由于ASSUME伪操作只是指定某个段分配给哪一个段寄存器,它并不能把段地址装入段寄存器中,要把段地址装入段寄存器中,就必须在代码段中有对段地址装入相应的段寄存器中的指令。可用两条MOV指令完成这一操作。但是,代码段CS不需要这样做,这一操作是在程序初始化时完成的。
4.1.3汇编语言程序的语句类型 汇编语言源程序由若干条语句组成,语句分为如下两类。 1) 指令语句 指令语句能完成一定的操作功能,能够翻译成机器代码的语句。 指令语句的格式为: 【标号:】 指令助记符 【操作数】 【;注释】
4.1.3汇编语言程序的语句类型 2) 伪指令语句 伪指令语句也叫指示性语句,它只是为汇编程序在翻译汇编语言源程序时提供有关信息,并不翻译成机器代码,所以也不占用执行时间。 伪指令的格式为: 【符号名】 伪指令定义符 【参数表】 【;注释】
4.2 伪指令 • 4.2.1 常量 • 1.常量的类型 • (1)数值型常量 • 二进制数:以字母B结尾,例:10101001B。 • 十进制数:以字母D结尾(或省略),例:5678。 • 十六进制数:以字母H结尾,由0~9,A~F所组成,以字母A~F开头的十六进制数,须在字母前加上数字0。
4.2.1 常量 • (2)字符串常量 • 字符串常量是用单引号或双引号括起来的一个或多个字符,如‘ABC’或“ABC”,字符在机器内是以ASCII存放。字母大、小写在计算机内存放的是不同的数值,例如,‘B’在内存中为42H,‘b’在内存中为62H。
4.2.1 常量 • 2.常量或表达式赋值伪指令 • 可以用赋值伪指令给常量或表达式赋值,程序中凡是需要用到的地方就可以用这个符号名来代替 • (1)等值伪指令(EQU) • 格式:符号名 EQU 表达式 • 功能:将表达式的值赋给符号名。 • SUM EOU 34H;将常数34H赋给 SUM • NUM EQU EBP+31H;EBP+3赋以NUM
4.2.1 常量 (2)等号伪指令 格式:符号名=表达式 功能:将表达式的值赋给符号名。 MATH=20H ENG=3 ENG=MATH+ENG+10H 等号语句与EQU语句有同样的功能,区别在于在同一源程序中,EQU语句不允许对符号重复定义,而等号语句允许对符号重复定义。
4.2.2 变量 1. 变量的属性 段属性(SEG):变量所在段的段基址,它通常放在DS、ES、SS段寄存器中。 偏移属性(OFFSET):从变量所在段的起始地址到定义变量位置之间的字节数。 类型属性(TYPE):指变量占用存储单元的字节数。字节变量类型为BYTE,字变量类型为WORD,双字变量类型为DWORD。
4.2.2 变量 2. 变量定义伪指令 变量定义伪指令是为操作数分配存储单元,并给这个存储单元取一个名字,即变量名,同时为变量赋以初值。 【变量名】 DB/DW/DD/DF/DQ/DT 表达式l,… 功能:为变量分配存储单元,表达式可以是数值表达式、地址表达式、字符串、?、用逗号隔开的上述各项或DUP(表达式)。
4.2.2 变量 (1)数值变量定义语句 NUM DB 100,45H ;将64H,45H赋给字节变量NUM SUM DW 3456H ;将3456H赋给字变量SUM TOTAL DD 22334455H ;将22334455H赋给双字变量 TOTAL
4.2.2 变量 (2)字符串变量定义语句 定义字符串变量可以用DB伪指令,它为字符串中的每个字符分配一个字节的存储单元,在存储单元中存放的是字符的ASCII码值。 ABC DB ‘ABCDEF’ ;将字符串赋给变量ABC DATE DBW ‘BA’,‘DC’ ;将两个字符串赋给变量DATE
4.2.2 变量 (3)预分配存储单元 “?” 语句可以为数据项分配存储单元,但是存储单元中不预置确定的值,所以常用来预留存储单元。 BVAR DB ?;预分配1个字节单元 DVAR DW ?,?,?;预分配3个字单元
4.2.2 变量 (4)重复数据定义 DUP语句可以重复进行数据定义操作,用带DUP的表达式可以为若干重复数据分配存储单元,DUP表达式也可以嵌套。 D1 DB 3 DUP(0);定义D1为3个全为0的字节单元 D2 DW l0 DUP(0ABCDH) ;定义D2为10个全为0ABCDH的字单元 D3 DD 2 DUP (20H, 2 DUP(10H)) ;定义D3为20H,10H,10H, 20H,10H,10H
4.2.3 标号 标号是可执行语句的符号地址,用来表示指令在存储器中的位置。经常在转移指令中目标操作数字段出现,用以表示转移指令的目标地址。标号之后必需有一个冒号“:” 。 1.标号的属性 (1)段属性(SEG):指标号所在段的段基址,它通常放在DS、ES、SS段寄存器中。
4.2.3 标号 (2)偏移属性(OFFSET):指标号所在段中的偏移地址,即标号所在的地址与段基址之间的字节数。 (3)类型属性或距离属性(TYPE):用来说明该标号是段内引用还是段间引用。段内引用时为NEAR属性,指针占两个字节;段间引用时为FAR属性,指针占4个字节。
4.2.3 标号 2.定义类型属性伪指令LABEL 语句格式: 变量名或标号 LABEL 类型 (1)与变量连用,给下一条语句中的变量取—个新的名字,并可重新定义它的类型,其类型可以是BYTE、WORD或DWORD 。 (2)与标号连用 ,给指令地址定义一个新的标号,并可改变其类型属性NEAR或FAR 。
4.2.4 表达式 分为数值表达式和地址表达式两种类型。表达式的运算是在汇编时由汇编程序完成的,表达式的运算结果作为操作数参加指令规定的操作。 1. 数值表达式 MOV AX, 2+10H 指令中源操作数是一个数值表达式,其运算结果是个数值,指令执行后AX中存放的是该表达式的值。
4.2.4 表达式 2. 地址表达式 地址表达式的结果是一个存储单元的地址。当这个地址中存放的是数据时,称为变量;当这个地址中存放的是指令时,则称为标号。例如: MOV AX,ES:[BX+1001H] 指令中源操作数是地址表达式,其结果是一个存储单元的地址。
4.2.5 运算符 1. 算术运算符 算术运算符:+、—、*、/等,参加运算的数和运算的结果均为整数,除法运算的结果取商的整数部分。 2. 逻辑运算符 逻辑运算符:AND、OR、XOR和NOT,用于对常量进行按位操作。
4.2.5 运算符 注意,逻辑运算符与逻辑指令在形式上是一样的,但它们在语句中的位置不同。表达式中的逻辑运算符是只出现在指令的操作数部分,是由汇编程序汇编时完成运算;而逻辑指令是出现在指令的操作码部分,其运算是在指令执行时进行的。 OR AL,BH OR 80H MOV AL,CL AND 10000000B
4.2.5 运算符 3. 关系运算符 包括GT(大于)、GE(大于等于)、LT(小于)、LE(小于等于)、EQ(等于)和NE(不等于)6种。对两个操作数进行比较运算,结果为逻辑值。 MOV AX, 11 EQ 1011B ;11=1011B为真,(AX)=0FFFFH MOV BX, 10H EQ 32 ;20H大于32为假,(BX)=0
4.2.5 运算符 4. 修改属性运算符PTR 修改属性运算符PTR可以临时改变变量或标号原有的类型属性并赋予其新的类型属性。 DATA DB 10H,11H,12H,13H MOV EAX, DWORD PTR DATA ;修改DATA为双字型变量
4.2.5 运算符 5. 取值运算符 取值运算符包括SEG(返回段地址)、OFFSET(返回偏移地址)、TYPE(返回类型字节数)、LENGTH(返回变量单元数)和SIZE(返回变量总字节数)。它们不改变原操作数的属性,只是取操作数的某一属性,返回的结果是一个数值。
4.2.5 运算符 (1)SEG运算符 SEG运算符加在变量名或标号之前,返回的数值是该变量或标号所在段的段基址。例如; MOV AX,SEG VAR 如果变量VAR所在段的段基址为1000H,则该指令执行后AX的内容为1000H。
4.2.5 运算符 (2)OFFSET运算符 OFFSET运算符加在变量名或标号之前,返回的数值是该变量或标号的偏移基址。例如: MOV BX,OFFSET VAR 如果变量VAR在段内的偏移地址为2000H,则该指令执行后BX的内容为2000H。
4.2.5 运算符 (3)TYPE运算符 TYPE运算符加在变量名之前,返回的数值是该变量的类型字节数,DB为1,DW为2。当TYPE加在标号之前,返回的数值是这个标号的类型属件值, NEAR为-1,FAR为-2。 A1 DB 1,2,3,4,5,6,7,8 A2 DW l234H,5678H SF LABEL FAR SN: MOV BL, TYPE A1 ;BL=1 MOV BH, TYPE A2 ;BH=2 MOV DH, TYPE SF ;DH=-2
4.2.5 运算符 (4)LENGTH运算符 加在变量名之前,返回的数值是变量中所定义的元素个数。如果变量是用DUP说明的,则返回DUP前面的数值;如果没有DUP说明,则返回的值总是1。 B1 DB 100 DUP(0) B2 DW 4321H, 3859H MOV BX,LENGTH B1;等效MOV BX,100 MOV AX,LENGTH B2;等效MOV AX,1
4.2.5 运算符 (5)SIZE运算符 该运算符加在变量名之前,返回的数值是该变量所分配的字节总数。它等于LEGTH和TYPE两个运算符返回的乘积。例如,对于上例中所定义的变量B1、B2的返回值如下所示。 MOV BX, SIZE B1;(BX)=100H MOV CX, SIZE B2;(CX)=2
4.2.6段定义伪指令 内存是分段管理的,程序的不同部分应放在特定的段中。段定义伪指令就是为程序的分段而设置的。 段名 SEGMENT …… 段名 ENDS 任何逻辑段总是从SEGMNT语句开始,以ENDS语句结束,成对出现。
4.2.7 段寄存器指派伪指令 ASSUME 段寄存器名:段名[,段寄存器名:段名,…] 该语句通知汇编程序源程序中定义的段由哪个段寄存器寻址。 ASSUME语句是非执行语句,要求放在代码段内的段定义语句之后。
4.2.7 段寄存器指派伪指令 ASSUME语句仅仅约定了对逻辑段进行寻址操作时使用哪个段寄存器,而段寄存器的初值还必须在程序中用指令设置。 MOV AX,DATA MOV DS,AX 对CS的赋值是由操作系统系统自动完成的,程序员不用设置。
4.2.8 移动地址指针伪指令 ORG 表达式 ORG伪指令用来指定该语句之后的程序或数据开始存放的偏移地址。 ORG 2000H VAR1 DB 2,3,45H ;从偏移地址2000H开始存放变量VAR1
4.2.9 当前位置计数器$ 在汇编语言中,可以用$表示当前位置计数器的值。 DATA SEGMENT STR DB ‘GOOD’ COUNT EQU $ - STR DATA ENDS $表示当前的偏移地址,变量名STR表示上一条语句中变量STR的偏移地址,$-STR表示两个偏移地址之差,是以变量STR为首地址的连续字节数,即STR为首地址的字符个数。
4.2.10 程序结束伪指令END END伪指令作为汇编语言源程序的结束语句,一般放在源程序的最后一行。一个程序模块只允许有一个END语句。 格式: END 标号
4.3 操作系统资源的使用 为方便程序员编写输入/输出程序,系统提供了两组功能程序。一组固化在BIOS内,由几十个内部子程序组成,它们能完成对I/O设备、文件、磁盘等的管理和操作。另一组是操作系统DOS为用户提供的使用输入/输出设备的系统资源,它不仅使用简单,而且可以确保所开发的软件在同一操作系统下的兼容性。
设置功能号n(AH) 设置入口参数 执行INT 21H 分析出口参数 4.3.1 DOS系统功能调用 1. 系统功能调用方法 系统功能调用INT 21H是一个有近90个子功能的中断服务程序,这些子功能的编号称为功能号。INT 21H的功能大致可以分为四个方面:设备管理、目录管理、文件管理和其他。
4.3.1 DOS系统功能调用 2.基本I/O功能调用 (1)单个字符键盘输入(1、7、8号功能) 执行1号功能调用时,系统将扫描键盘,等待用户按键,一但有键按下,就将键值(相应字符的ASCII码值)读入,先检查是否是<Ctrl+Break>键,若是,则退出命令执行;否则,将键值送入AL寄存器,同时将这个字符显示在屏幕上。