汇编程序的组成
本章节介绍:
• 语句
• 标示符
• 保留字
• 注释的应用
• 操作数
• 表达式
数值表达式
地址表达式
返回值操作符
属性操作符
数据的定义
标号与变量的属性
伪指令
a.存储模型说明伪指令.MODEL
b.段伪指令SEGMENT和结束伪指令ENDS
c.过程开始伪指令 PROC和结束伪指令ENDP
d.段使用设定语句伪指令Assume
e.整个程序结束伪指令END
f.简化段伪指令
g.等值伪指令EQU
h.ORG伪指令
一个完整的源程序的组织
语句
汇编程序由语句组成
• 汇编语言语句的通用格式:
[标示符] 操作符 [操作数][;注释]
表示符, 操作符, 操作数被至少一个空格或者制表符分开。
• 语句的两种类型:
1) 指令,被汇编器转换成机器代码;
[标号:] 操作符 [操作数] [;注释]
2) 伪指令 ,只告诉汇编器要执行的具体行动,不产生机器代码
[名称/变量] 指令 [表达式/参数 ] [;注释]
[标示符] 操作符[操作数] [;注释]
语句的两个例子:
[标号:] 操作符[操作数] [;注释]
L1: MOV AX, 0 ;把 0 移到 AX
[名称/变量] 指令[参数][;注释]
counter DB 1 ;定义字节的值 1
标示符
标示符的两种类型:
1. 标号 指令,过程,段的地址
例如: 下面语句中的Main
Main: PROC FAR
2. 名称/变量 数据单元的地址
例如:下面语句中的Counter
Counter DB 0
• 标示符 可以使用一下字符:
字母: A~Z, a~z ; (不区分大小写)
数字: 0~9 (不能作为第一位) ;
特殊字符: ? _ $ . @
• 标示符的第一个字母必须是字母或者专用字符,但专用字符的“.”除外。
• 不能用保留字作为标示符。
• 标示符最大长度为31个字符。
保留字
汇编语言里的某些名字是为它们固有的用途而保留的,只再特殊情况下使用。
种类:
• 指令,如MOV和ADD,是计算机可执行的操作;
• 伪指令, 像END或SEGMENT,是为汇编程序提供信息。
• 操作符, 如FAR和SIZE,可以在表达式中使用。
• 预定义符号, 如@DATA 和 @Model, 它们在汇编期间向程序返回信息。
•
程序注释
遍及整个程序的注释的使用可以改善程序的清晰度。
• 注释用一个分号(;)开始.
汇编程序假定在一行中所有在它右边的字符都是注释
注释可以包含任意可打印字符,包括空格在内。
例子:
ADD AX, BX ; 累计
注释不会产生机器码,因此它不会影响汇编程序的大小和运行。
操作数
• 操作数提供操作要用的信息。
• 有些指令无需操作数,有些却又一个或者两个操作数。
• 对于指令来说,操作数的地址包含在操作数项中。
• 操作数项由常量,寄存器,标号,名称/变量或者表达式(一个或多个)组成
表达式
表达式分为数值表达式和地址表达式。
数值表达式中的值是可以在汇编过程中被汇编器计算的。
数值表达式
1) 常量
2) 算术表达式
3) 关系表达式
4) 逻辑表达式
5) 值表达式中其他操作符
6) 操作的优先级(从高至低)
1)常量
十进制常量: 12D,12
十六进制常量: 0FAH
二进制常量: 00000001B
字符串常量:
是用单引号或者双引号括起来的一个或者多个字符,
它的值是字符的ASCII码值。
2) 算术表达式
算术表达式包括 +,-,*, /, MOD (除后的余数).
例如:
ADD AX, 100H /3*2-1
地址表达式
地址表达式表示的内存中存放操作数的地址
标号, 名字/变量(立即地址), [BX], [SI] ,[DI]都是特殊的地址表达式。
地址 ±值=地址
例子:
SUN+1 =SUN下一位的地址
注意:并非SUN的内容加1;
3.值–返回操作符
有 TYPE, LENGTH, SIZE, OFFSET, SEG.
1)TYPE—返回 变量或者标号的属性类型的值。
格式: TYPE 变量 或者标号
字节变量 属性类型的值1
字变量 2
双字变量 4
近标号 -1
远标号 -2
TYPE 变量 或者 标号
; 返回变量或者标号属性类型的值
SEG 变量 或者 标号
;返回变量或者标号所在的段的段地址
OFFSET 变量 或者 标号
;返回变量或者标号的偏移地址
4. 属性操作符
1) PTR—指定或者更改变量或者标号的类型。
格式: 类型 PTR 地址表达式
注意: PTR不分配内存空间。
例子:
MOV [SI], 1 ;出错
MOV BYTE PTR [SI], 1 ;指定字节类型
MOV WORD PTR [SI], 1 ;指定字类型
数据定义
EXE程序中的数据段
是用来为定义常量,工作区,输入/输出区和未定义值的。
• 数据定义的格式:
[变量] Dn 表达式1[,表达式2,…] [; 注释]
数据项的名字是唯一的,也是具有描述性的。
• Flag DB ?
;这个表达式定义一个没初始化的值,但它必须符合定义的大小
•一个表达式可以 包含多个被逗号“,”隔开的常量,只被行的长度所限制。
如下所示:
• Flag DB 21, 22, 23, 24, 25, …
汇编器把这些常量定义在相邻的字节
MOV AL, Flag+3 ; 24(18H) 放进AL
重复操作符 DUP
[名称/变量] Dn重复计数DUP(表达式)…
例子:
Buffer1 DB 5,0, 5 DUP(?) ;7 字节
Buffer2 DW 25DUP(‘ab’) ;25*2 字节
Buffer3 DW 1,5DUP(1,2,4 DUP(0)) ;62 字节
表达式可以定义 并初始化一个字符串或一个数字常量
字符串
例子:
DB “Sam’s CD” ;单引号
DB ‘Sam”s CD’ ;双引号
• 汇编器把字符串当成是普通的ASCII码进行存储
·在MASM中, DB (字节 )是定义2个以上字符的字符串的仅有格式,这些字符以左相邻的方式并按照正常的从左到右的顺序存放
34
例子: 32 L1
MESS DB ‘OK’ A 41
FLAG DW ‘Ab’ b 62 FLAG
L1 DB ’24’ ;代表着十六进制 3234 K 4B
O 4F MESS
标号和变量的属性
• 变量和标号都是存储单元的偏移地址。
• 变量指示的存储单元中存放数值;
• 标号指示的存储单元中存放的是机器指令的代码。
•
• 标号是语句的一部分,用在指令前表示对应语句的地址,标号后一定要加冒号(:)
标号指示着指令代码所在的第一个内存单元的偏移地址
变量(名称)指示着数据项所在的第一个内存单元的偏移地址
• 3 标号和变量的属性:
1) 段值
标号和变量指示的内存单元 所在的段地址
2) 偏移
标号和变量指示的 起始内存单元地址 的段内偏移地址。
3) 类型
标号的类型主要分为近(段内)和远(段间),属性值分别是-1和-2。
变量的主要类型有字节,字,双字。
伪指令
• 只在汇编过程中起作用,并且不产生机器可执行的代码。
• 功能:
定义数据, 分配内存单元,指出程序的结束,等等。
变量定义伪指令
表3-1 各种数据定义伪指令
描述 伪指令 意义 类型属性值
Byte DB byte 1
Word DW word 2
Double word DD Dword 4
Far word DF F word 6
Quad word DQ Qword 8
Ten bytes DT Tbyte 10
段伪指令
PROC 伪指令
• 代码段由一个或者多个过程组成,
• 过程必须完全包含在段中。
• 格式
过程名 PROC Attribute ;第一切入点
… ;执行的指令
过程名 ENDP ;过程结束
• 过程名必须存在,必须是唯一的,而且必须遵循汇编语言的命名惯例。
• 属性是NEAR(默认) 或者 FAR.
• 在同一段中被调用的过程就是近过程,可以通过 偏移地址 来访问。
•在段外的被调用的过程就是远过程,可以通过 段地址:偏移地址 来访问。
段使用设定语句
Assume 伪指令
为有效的产生目标代码,
汇编程序要了解各程序段与段寄存器之间的对应关系
•段寄存器与程序段的对应关系 由 段使用设定语句说明。
•通过Assume伪指令 设定的段名与段寄存器CS,DS和SS之间的对应关系。
段使用设定语句的简单格式:
ASSUME 段寄存器名:段名[,段寄存器名:段名…]
操作符 操作数
Assume SS:堆栈名, DS:数据名,CS:代码段
例如, ASSUME CS:CSEG, DS:DSEG
告诉汇编程序:CS寄存器对应CSEG段,DS寄存器对应DSEG段。
段使用设定语句是伪指令语句,
它不能设置段寄存器的值,
即段寄存器还没有指向对应的段。
所以在程序中
还需要用指令语句
来给数据段寄存器和附加段寄存器 赋值。
• 如果你的程序没有用到ES寄存器,
• 则可以省略对ES的说明
• 或者编码为ES:NOTHING
• 操作数可以以任何顺序出现。
• 你可以用ASSUME来更改相关的段和段寄存器。
Example:
ASSUME CS:CSEG,DS:DSEG1, ES:DSEG2
… ;一些指令
ASSUME CS:CSEG,DS:DSEG2, ES:DSEG1
源程序结束语句
End 伪指令
源程序结束语句的一般格式:
操作符 操作数
END [标号]
END [proc-name]
• 在大多数程序中,
• 操作数包含的第一个过程名,
• 或 PROC指定为FAR的过程名,
• 程序要从这里开始执行。
• ENDS伪指令结束一个段,
• ENDP伪指令则结束一个过程,
• END则是结束整个程序。
结束程序运行的指令
• INT 21H是一种常见的DOS中断指令,
• 用AH寄存器中的功能码,来指定要执行的动作。
INT 21H中断指令,
若AH寄存器中的功能码是4CH时,
则CPU执行完DOS中断指令INT 21H,
就结束程序的执行,
返回DOS操作系统了。
我们还可以使用此操作,在AL中返回代码。正常的程序完成后的返回代码,通常是0(零)。
•INT 21H的功能码4CH已经取代了INT 20H的运作,INT 21H的功能码00H最初是用来结束处理过程的。
简化的段伪指令
为了使用简化的段伪指令,在定义任何段之前,必须初始化存储模型。
存储模型说明伪指令 格式:
. MODEL 存储模型
该伪指令以符号点“.”引导
.MODEL 伪指令自动定义所需的ASSUME 语句
•为了说明采用SMALL存储模型,只要在源程序首使用如下伪指令:
• .MODEL SMALL
. STACK [大小] ;默认大小是1024byte
. DATA
. CODE [名称]
• 一个简化段开始,意味着上一个段的结束。
• 伪指令END表明最后一个段(整个代码段程序)的结束。
等值伪指令EQU
格式:
表达式名 EQU 表达式
• EQU伪指令定义一个值,在其他的指令中,汇编器可以用来代替。
• EQU是简单的替换,在生成的对象的程序上,它不需要额外的存储空间。
• 表达式可以是常量,值表达式,字符串,关键词,操作符。
• 不允许重新定义一个表达式的名称。
• 表达式中通常不允许向前引用表达式的名称。
例子:
COUNT EQU 100
;汇编器把DB COUNT DUP ? 转为 DB 100 DUP ?
DATA EQU COUNT+2
;汇编器用COUNT+2的地址来替换DATA
HELLO EQU ‘How are you’
;汇编器用来字符串‘How are you’替换 HELLO
MOVE EQU MOV
COUNTER EQU CX
MOVE AX, CX ;MOV AX, CX
MOV COUNTER, 100 ;MOV CX,100
ORG 伪指令
格式: ORG 表达式
• 可以用ORG 伪指令来改变内存单元地址计数器的内容。
• 表达式必须从一个2字节的绝对值数(不能是象征性的名称)开始,而且是当前指令的下一个字节的内存单元地址
• ORG /伪指令包含一个美元符号($)是指一个操作数的内存单元地址计数器的当前值/在当前指令的第一个字节的位置 。
例1:
ORG 100H
BEGIN MOV AX,1234H ; BEGIN 的偏移地址是100H
ORG $+8 ; 在内存中跳8个字节
JMP $+6
;在当前指令的第一个内存单元之后,跳到第六个字节
;$+6另一条指令的开始的内存单元