微机原理及应用 主讲:谢维成 http://xweicheng.ys168.com scxweicheng@yahoo.com.cn 第 4章 汇编语言程序设计 ? 汇编语言的格式 ? 语句行的构成 ? 指示性语句 ? 指令语句 ? 汇编语言程序设计及举例 4.1 汇编语言的格式 (P111、 P99<3>) 8086汇编语言程序举例 MY_DATA SEGMENT SUM DB ? MY_DATA ENDS MY_CODE SEGMENT ASSUME CS:MY_CODE,DS:MY_DATA PORT_VAL EQU 3 MAIN PROC FAR GO: PUSH DS MOV AX,0 PUSH AX MOV AX,MY_DATA 4.1 汇编语言的格式 MOV DS,AX MOV SUM,0 CYCLE: CMP SUM,100 JNA NOT_DONE MOV AL,SUM OUT PORT_VAL,AL HLT NOT_DONE: IN AL,PORT_VAL ADD SUM,AL JMP CYCLE 4.1 汇编语言的格式 RET MAIN ENDP MY_CODE ENDS END GO 1、汇编语言源程序是分段的,通常每个模块程 序包括数据段、堆栈段和若干代码段。 2、每个程序结构类似,可以复制。 4.2 语句行的构成 指令性语句,其格式为: 标号:(前缀)指令助记符 操作数;注释 GO: PUSH DS 指示性语句,又叫伪指令,其格式为: 变量 伪指令 操作数 ;注释 SUM DB ? 4.2 语句行的构成 4.2.1 标记 (P112) 机器语言 —用二进制数来表示指令和数据. B0 64 什么意思?这就是机器语言。既不直观, 又不易理解和记忆. MOV AL,64H ;大家很清楚,这就是助记符。 助记符 —反映指令的功能和主要特征,便于人 们理解和记忆。 返回 4.2 语句行的构成 指令除了操作码以外,还有一个操作数问题。 操作数可能放在存储器中,这就涉及一个地址问 题。程序中遇到转移指令或调用指令, 涉及地址转移, 若采用具体地址就不很方便, 一旦有错改动就很麻烦。 于是人们采用 标号 或 符号 来代替地址,例: LP1: … ┇ LOOP LP1 汇编语言 —用助记符,符号地址以及标 号等 符 号 书写的程序。用汇编语言编写的程序叫 源程序 。 返回 4.2 语句行的构成 汇编: 汇编源程序需翻译成机器语言,变成可执 行文件,机器才能执行,这个翻译过程叫 汇编 。 汇编语言是面向具体计算机硬件的语言 ,和机器 密切相关。它最大缺点是可读性差,编程效率低。 高级语言 —编程时不需要对机器指令系统有深入了 解,稍加培训即可掌握。可读性强,功能强。 为什么要用汇编语言?汇编语言编写的程序 节省内 存,执行 速度 快 ,并为用户直接控制对象提供了手段。 故 实时性要求很高的程序多采用汇编语言程序 。 4.2 语句行的构成 操作码: 是一个助记符,它可以是指令、伪指令(又叫 伪操作)或宏指令。 操作数: 由寄存器、存储单元、数据项或其表达式构 成。汇编时一个表达式得到一个值。 注释: 用来说明程序或语句的功能, 用 分号; 作 为 注 释开始。 其中名字和注释视情况而定,可有可无. 4.2 语句行的构成 1、源程序 源程序 通常由一个或几个程序模块组成,每个模 块包括数据段、堆栈段和若干代码段。代 码段可有若 干个过程,过程中的语句分为两类: 指令性语句,其格式为: 标号: (前缀)指令助记符 操 作数;注释 指示性语句,又叫伪指令,其格式为: 变量 伪指令 操 作数 ;注释 4.2 语句行的构成 2、指令性语句 指令性语句 是计算机可执行的,而指示性语句不 能执行 ,用来定义变量,分配存储单元,指示程序开始 和结束等。 这两种语句的差别: 在形式上: 带不带冒号,是否可转向它. 在本质上:汇编时能否形成对应的机器码. 4.2.1 标记 - 4.2.2符号 数据项 数据项包括常量、变量、标号及表达式,下面分 别 加 以介绍。 1.常量 (1)数字常量 二进制常量,以 B结尾 十进制常量,以 D结尾或省略(汇编语言中默认无标 记数为十进制数) 十六进制常量,以 H结尾,如0A8C6H. 4.2.1 标记 - 4.2.2符号 (2)字符串常量 用引号引起来的字符或字符串也代表常数。 例 :’A’,’BCDE’,汇编时被翻译成对应的 ASCII码 41H和 42H,43H,44H,45H。 返回 4.2.1 标记 - 4.2.2符号 2.变量 变量是内存中的数据区 ,在程序中作为存储器操 作数来使用。如例子中BLOCK(在数据段中定义) 变量有三种属性: ①段 值 —变量定义所在段的段地址 ②偏移量 —变量单元地址与段起始地址之 间的位移量。 ③类 型 —有字节、字和双字三种。 4.2.1 标记 - 4.2.2符号 标号 标号 是某条指令所存放单元的符号地址,可作为转移指 令或CALL指令的转移地址。 标号也有三种属性:段值总是 在C S段 寄 存 器 中 ,偏移量 概念与变量同,类型分NEAR和FAR两种。 NEAR—表示标号所在语句与转移指令 或调 用指 令 在 同 一 码段内,只需改变IP即可。 FAR—标号所在语 句 与 转 移 指 令 或 调 用 指 令 不 在 同 一 码 段内。 若没有对类型进行说明,默认为NEAR。 4.2.3 表达式 4.表达式 表达式 是常数、寄存器、标号、变量与一些运 算符组合的序列 ,分数字表达式和地址表达式两种。 汇编时按一定的优先规则对表达式进行计 算 后 可 得 到一个数值或一个地址。 下面介绍五种运算符 : 4.2.3 表达式 (1)算术运算符 有+、-、*、/,以及M OD,其中M OD表示除法运 算后得到的余数。例: 19/7的商是2,19 MOD 7则为5(余数) 算术运算符可以用于数字表达式,例: MOV AL,2*7 汇编后为B0,0E 算术运算符也可以用于地址表达式,对地址运算 的结果应有明确的物理意义, 例两个地址的乘或除无 意义,而加或减则可以,例: LEA SI,SUM+3 表示 变量 SUM的地址加上3得到的和作为新存储 器地址。 4.2.3 表达式 (2)逻辑运算符 逻 辑 运 算 符 有 AND、OR、XOR 和 NOT, 它 们 只 能 用 于数字表达式中。 例:MOV CL,36H AND 0FH 经汇编后:MOV CL,06H 这些逻辑运算符也是8086/8088的指令助记符,会 不 会 造 成 混 乱 呢 ?不 会 的,前者在汇编时进行,而后者 在指令执行时进行的。 例:AND DX,PORT_VAR AND 0FEH 后一个逻辑运算符AND在汇编时进行, 若PORT_VAR 为81H,则汇编后表达式算出为8 0H.执行前一个指令助 记符AND时,将(DX)与80H相与,结果在DX中。 4.2.3 表达式 (3) 关系运算符 共有6个,它们为: EQ(相等),NE(不等),LT(小于),GT(大于), LE(小于或等于),GE(大于或等于) 关系运算符的两个操作数必须都是数字或者是同 一段内的两个存储器地址。 关系为真,结果为0FFFFH 关系为假,结果为0 例:MOV BX,PORT_VAL GE 5 若PORT_VAL的值大于等于5,则汇编后为: MOV BX,0FFFFH 若PORT_VAL的值小于5, 则汇编后为: MOV BX,0 4.2.3 表达式 (4)数值返回操作符 它可以把存储器一些特征作为数值送回。 这些操作符有OFFSET,SEG,TYPE,SIZE及LENGTH。 例:MOV SI,OFFSET STRI1 ;代表将变量 STRI1处的地址偏移量取到SI中. 注意与 MOV SI,STRI1的差别. 但它与 LEA SI,STRI1类似. 与此类似,SEG运算符用来取存储单元的段值, 例: MOV AX,SEG STRI1 ;将变量STRI1所 MOV DS,AX ;在段值取到DS中 4.2.3 表达式 TYPE操作符 TYPE操作符用来取存储器的单元类型,各单元类 型对应值如下: 存储器单元类型 对应值 DB(字节) 1 DW(字) 2 DD(双字) 4 若BUFFER1存储区是用如下伪指令定义的: BUFFER1 DB 100 DUP(?) 则 TYPE BUFFER1等于1 4.2.3 表达式 LENGTH操作符 LENGTH操作符用来计算一个存储区的单元(单元 可以是字节,字或双字)的数目。 注意LENGTH返回的存储区必须用复制操作符 DUP( )来定义,否则返回值为1。 例: 若FEES被定义为:FEES DW 4,5,6 则 MOV CX,LENGTH FEES 汇编后,MOV CX,1 操作符 SIZE用来计算一个存储区的 字节总数 。 4.2.3 表达式 三者关系 例: 若BUFFER2存储区是用如下伪指令定义的: BUFFER2 DW 200 DUP(0) 则: TYPE BUFFER2 等于2 LENGTH BUFFER2 等于200 SIZE BUFFER2 等于400 4.2.3 表达式 (5)类型操作符PTR 用来对存储单元规定类型,通常和伪指令 BYTE,WORD等连起来使用。 例:MOV BYTE PTR[DI],0 MOV WORD PTR[DI],0 而 MOV [DI],0 ;类型不定 PTR也可用来对已经规定了类型进行更改 4.2.3 表达式 例:STRI1 DW ? ; 定义为字类型 可用如下语句: PP EQU BYTE PTR STRI1 QQ EQU BYTE PTR STRI1+1 通过PP,QQ把STRI1和STRI1+1又规定为字节类型。 MOV STRI1,AX 是合法的 MOV AL,STRI1 是非法的 只能用: MOV AL,PP 或 MOV AL,BYTE PTR STRI1 4.3 指示性语句(伪指令) (P120) 4.3 伪指令 常用的伪指令有: 符号赋值伪指令 变量定义伪指令 段定义伪指令 过程定义伪指令 结束伪指令 4.3.1 符号赋值伪指令 1.等值伪指令EQU 格式为:符号名 EQU 表达式 或:新符号名 EQU 老符号名 例: CONSTANTEQU 100 NEW_PORT EQU PORT_VAL+1 EQU伪指令在未解除前,不能重新定义。 4.3.1 符号赋值伪指令 2.等号(=)伪指令 与EQU类似,但允许重新定义 例: ┇ EMP=7 ;值为7 ┇ EMP=EMP+1 ;值为8 4.3.1 符号赋值伪指令 3.解除伪指令PURGE 已用EQU定义的符号,可用PURGE解除,再重 新定义。 例:PURGE NEW_PORT NEW_PORT EQU POTR_VAL+8 4.3.1 符号赋值伪指令 变量 是内存中数据区的名字,故这类伪 指令又可叫数据定义伪指令。这类伪指令格 式为: 变量名 伪指令助记符 操作数 ;注释 其中变量名用符号地址表示,后面不能跟 冒号,它可有可无。 4.3.2 数据定义语句 (P121) 伪指令助记符有如下几种: DB 用来定义字节 DW 用来定义字 DD 用来定义双字 操作数可以是常数或表达式 注释用来说明伪指令的功能,它亦可有可无。 例1:DATA_BYTE DB 10,5,10H DATA_WORD DW 100H,100,-4 DATA_DW DD 2*30,0FFFBH 4.3.2 数据定义语句 0A 05 10 00 01 64 00 FC FF 3C 00 00 00 FB FF 00 00 DATA_BYTE DATA_DW DATA_WORD 10 5 10H 100H 100 -4 60 0FFFBH 汇编后如图所示: 4.3.2 数据定义语句 例2:操作数可以是字符串 MASTERLI DB ‘HELLO’ 汇编后如下: 48 45 4C 4C 4F MASTERLI ‘H’ ‘E’ ‘L’ ‘L’ ‘O’ 注意下面的不同: DB’AB’ DW’AB’ 41 ‘A’ 42 ‘B’ 42 ‘B’ 41 ‘A’ 4.3.2 数据定义语句 操作数 ?用来保留存储空间,但不存入数据. 例3: ABC DB 0,1,?,?,? LPI DW ?,54,? 汇编后如下图示: 00 01 ╳ ╳ ╳ ╳ ╳ 36 00 ╳ ╳ ABC LPI 0 1 ? ? ? ? ? 54 4.3.2 数据定义语句 操作数字段还可以用复制操作符 DUP来 缩 写,如上面 ABC亦可写成: ABC DB 0,1,3 DUP(?) 又如: DO-2 DB 2 DUP(0,1,2,?) 与 DO-2 DB 0,1,2,?,0,1,2,?等价 在伪操作的操作数字段中若使用$,则表示的是地 址计数器的当前值。 4.3.2 数据定义语句 ? 例: BUFFER DW 3,4,$+3 ? 设BUFFER的偏移地址为0088H,则汇编后如下图所示: 03 00 04 00 8F 00 BUFFER 0088H 008CH+3 返回 4.3.3 段定义语句 (P127) 段定义伪指令 因8086/8088 C PU的存储器是分段的,这就需要 有段定义语句。 与段有关的伪指令有: SEGMENT、ENDS、ASSUME、ORG 段定义伪指令的格式如下: 段名 SEGMENT ┇ 段名 ENDS 返回 4.3.3 段定义语句 SEGMENT、ENDS 这两 个伪 指令总是成对出现,二者前面的段名 一致。二者之间的删节部分,对数据段、 附 加 段 及 堆栈段,一般是符号、变量定义等伪指令 。 对 于 代 码段则是指令及伪指令。 此外,还必须 明确段和段寄存器 的关系,这可 由ASSUME语句来实现。其格式为: ASSUME Seg-reg:SEGNAME [,…] 其 中 段 寄 存 器 名 必 须 是 CS、DS、ES 或 SS中 的 一 个,而段名则是由SEGMENT及ENDS定义的段名。 返回 4.3.3 段定义语句 ASSUME 需指出的一点,A SSUME伪指令只是告知汇编程序 有关段寄存器与段的关系, 并没有给段寄存器赋予实 际的初值。故例中 MOV AX,DATA MOV DS,AX MOV ES,AX 如程 序中 用到堆栈段,也需装入实际的初值。 而代码段不需要用户装,由初始化程序装入。 返回 4.3.3 段定义语句 (P127) 伪指令ORG 伪指令O RG规定了段内的起始地址或偏移地址, 其格式为: ORG <表达式> 表达 式的 值即为段内的起始地址或偏移地址, 从此地址起连续存放程序或数据。 返回 4.3.4 过程定义语句 (P131) PROC、ENDS、CALL、RET 过程定义格式为: PROC、ENDS、CALL、RET 段定义伪指令的格式如下: 过程名 PROC ┇ RET 过程名 ENDP 返回 4.4 指令性语句 (P132) 指令? 返回