一,基本数据
1.标识符
- 必须由字母,数字及特殊符号(? , · , @ , _ , $)组成,且必须由字母打头
- 字符总数限制在 31 个以内
- 不能使用系统专用保留字。保留字主要有 CPU 中各寄存器名,指令助记符,伪指令,运算符(GE,EQ),操作符(PTR,SEG 等)
2.常数
数字常数
进制 | 后缀 |
---|---|
二进制 | B |
八进制 | Q |
十进制 | D 或不跟字母 |
十六进制 | H |
注意:常数的第一位必须是数字(可以加个0)
字符串常数
字符串常数最长允许有 255 个字符,形式是用单引号 ’ ’ 括起来。
(汇编时单引号内的字符都以 ASCLL 码的形式存放在内存单元中)
3.变量
其实是存储单元的符号,即与某一数据项第一字节相对应的标识符
变量的三个属性:
属性 | 含义 |
---|---|
段地址(SEG) | 变量所在段的段地址 |
偏移地址(OFFSET) | 变量所在段内的偏移地址 |
类型(TYPE) | 变量的类型是所定义的每个变量所占据的字节数 |
汇编语言中,变量的类型有 字节变量,字变量,双字变量,四字变量和十字节变量
DB(字节),DW(字),DD(双字),DQ(四字),DT(十个字节)
4.标号
可执行指令语句地址的符号表示,即用标识符来表示地址
可用作转移指令和调用指令的目的操作数,以确定程序转移的目的地址
标号的三个属性:‘’
属性 | 含义 |
---|---|
段地址(SEG) | 与标号对应的指令首字节所在段的段地址 |
偏移地址(OFFSET)} | 与标号对应的指令首字节所在段内的偏移地址 |
类型(TYPE) | NEAR(表示标号是近标号,只能在本段内被引用),FAR(表示标号是远标号,可以在段间引用) |
二,伪指令语句
没有对应的机器指令,最终不被CPU所执行,而是由编译器执行的指令
其类型有:
- 数据定义 伪指令语句(常用)
- 标识符赋值与解除 伪指令语句(常用)
- 段定义 伪指令语句(常用)
- 过程定义 伪指令语句(常用)
- 程序开始与结束 伪指令语句(常用)
- 方法定义 伪指令语句(灵活)
- 结构定义 伪指令语句(灵活)
- 分组 伪指令语句(灵活)
- 其他 伪指令语句(灵活)
2.1 数据定义
指令格式:
变量名 助记符 操作数1,操作数2,操作数3... ;助记符指: DB,DW,DD,DQ,DT
变量名 助记符 n DUP(操作数表) ;操作数表就是 操作数1,操作数2,操作数3...(用逗号隔开)
功能:从变量名指定的存储单元开始存放操作数表中的各操作数,如果不需要存入任何数据,则起到分配内存单元的作用。
变量名:一个用标识符表示的符号地址,可省略,其值等于操作数第一个字节的偏移地址。
助记符: DB(字节),DW(字),DD(双字),DQ(四字),DT(十个字节)
操作数:可以是 常数,变量,表达式,字符串,?(表不确定的数),标号。
n DUP() :定义数组,把括号里的数重复存放 n 次。
DATA1 DB 15H,12H ;定义两个字节变量,第一个(15H)地址在 DATA1,第二个(12H)在 DATA1+1
DATA2 DD 2*40H,0AABBH ;定义两个双字变量,DATA2 为首地址的内存:80H,00H,00H,00H,BBH,AAH,00H,00H
注意:
定义字符串变量时,在多于两个字符的情况下,最好用 DB 伪指令来定义。
2.2 标识符赋值与解除
该类指令均不占用内存
2.2.1 等值伪指令语句 EQU
指令格式:
标识符 EQU 操作数 ;操作数可以是 变量,标号,常数,指令,表达式
功能:用来给操作数定义一个标识符,程序中用到该标识符即用操作数代替,在同一个程序模块中只需定义一次。
DATA EQU 100
DATA1 EQU DATA+1
CI EQU ADD ;将加法指令赋给 CI
注意:操作数中有变量或标号要先给这些变量或标号定义,否则出错
2.2.2 等号伪指令语句 “=”
指令格式:
标识符 = 操作数
功能:与EQU类似,但是EQU不允许一个标识符重复定义,而 “=” 允许一个标识符重复定义
2.2.3 解除伪指令语句 PURGE
指令格式:
PURGE 标识符1,标识符2,...,标识符n
功能:解除 EQU 的标识
若某标识符解除后就可以用 EQU 重新定义
2.2.4 别名定义伪指令语句 LABEL
指令格式:
别名 LABEL 类型属性
功能:给该语句下一行所使用语句中的变量或标号取一个别名,并可重新定义它的类型属性。
DATAB LABEL BYTE
DATAW DW 1234H,5678H ;DATAB就是DATAW的别名,一样的段地址与偏移地址,但是是字节型的
2.3 段定义伪指令语句
2.3.1 段结构定义
指令格式:
段名 SEGMENT 定位类型 组合类型 ‘分类名’
...
...(逻辑段内容)
...
段名 ends
segment 和 ends 是一对成对使用的伪指令。
功能:定义一个段(将一个逻辑段的内容定义成一个整体),segment 说明段开始,ends 说明一个段结束。
参数:
①定位类型(可省略,默认为PARA)
定位类型 | 含义 |
---|---|
PARA | 规定20位的段起始地址为 XXXX XXXX XXXX 0000B |
BYTE | 规定20位的段起始地址定位在存储单元的任何字节地址 |
WORD | 规定20位的段起始地址定位在字的边界,即段的首地址是偶数 |
PAGE | 规定20位的段起始地址为 XXXX XXXX 0000 0000B |
②组合类型(可省略,默认为NONE) | |
组合类型 | 含义 |
– | – |
NONE | 规定该段与其他同名段不连接,独立存在于存储器中 |
PUBLIC | 规定该段与其他模块中的同名段在满足定位类型的前提下依次由低地址到高地址连接起来,连接顺序由LINK软件确定 |
COMMON | 规定该段与其他模块中的同名段有相同的起始地址,采用覆盖的方式存放,公共存储区的长度与各段中长度最大的相同 |
AT 表达式 | 该段的起始地址定位在表达式所指定的节(16的整数倍)边界上 |
STACK | 此参数在堆栈段中不可省略,用来指定该段为堆栈段,各个模块中的堆栈段采用顺序连接方式组合 |
MEMORY | 本逻辑段定位在几个逻辑段中地址最高的存储区。当有多个MEMORY逻辑段连接时,除第一个带MEMORY参数的逻辑段外,其他带此参数的同名段按照COMMON方式处理 |
③‘类别名’ | |
将所有分类名相同的逻辑段组成一个段组,给参数必须用单引号括起来,类别名不超过40个字符,该参数可省略。 | |
注意: |
- 一个段必须有一个名称来标识,如例子中 codesg 就是段名,这个段名最终将会被编译,连接程序处理为一个段的段地址。
一个源程序中将所有将被计算机所处理的信息:指令,数据,栈,被划分到了不同的段中
一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
2.3.1 段分配
用户可定义多个逻辑段,但只允许4个逻辑段同时有效。因此需要用段分配指令来指定当前有效的逻辑段,并将这些有效的逻辑段分别定义成代码段,数据段,堆栈段及附加段。
指令格式:
ASSUME CS:段名,DS:段名,SS:段名,ES:段名
功能:定义当前有效的4个逻辑段,指明段和段寄存器的关系。
注意:
- ASSUME助记符 不可省略,一般放在代码段的开始。说明当前代码段,数据段,堆栈段及附加段是如何定义的。
- 段名必须是已经段定义过的名字
- 4个逻辑段不一定全部都要定义,通常代码段和数据段是必须的,附加段可以省略。但当代码段中使用了串指令时,必须设置附加段。
- 可以用
ASSUME 段寄存器名 : NOTHING
来取消已经由ASSUME所指定的段寄存器与逻辑段的关系。 - ASSUME 只指定某个段分配给相应的段寄存器,并将代码段的段基址自动装入CS段寄存器中,但不能将其他短的段基址装入相应的段寄存器中,所以在代码段的开始必须安排一段初始化程序,把其他段的段基址分别装入相应的段寄存器中。
2.4 过程定义伪指令语句
也叫 子程序
指令格式
过程名 PROC 属性
...
...(过程内容)
...
RET
过程名 ENDP
功能:定义一个由主程序可以用 CALL 指令调用的过程
过程名:定义过程所取的名字,不可默认,是子程序的入口的符号地址
属性:
属性 | 含义 |
---|---|
段地址 | 给过程所在段的段地址 |
偏移地址 | 过程首字节所在段内的偏移地址 |
距离属性 | NEAR(表示过程允许在段内调用),FAR(表示允许过程在段间被调用) |
注意:
- 过程中至少有一个 RET 指令,可以在任何位置
- 使用CALL 调用的语句:
CALL 过程名
- 过程允许嵌套和递归调用,其深度由堆栈段的容量决定,这时不仅要考虑将当前的地址压入堆栈,还要考虑将需要保护的参数压入堆栈,否则会影响主程序的运行状态。
2.5 程序开始与结束 伪指令语句
######(1)目标模块命名
指令格式:
NAME 程序名
TITLE 文本名
功能:为源程序目标模块赋一个程序名
NAME:定义一个程序名,该程序名在汇编语言源程序列表文件的每一页的开头输出。
TITLE:功能与 NAME 基本相同,将文本名赋给源程序目标模块作名字
######(2)定位
指令格式:
ORG 表达式
功能:给汇编语言程序设置指令位置指针,给出该定位下一条语句的起始偏移地址
用来改变某条指令或数据的存放位置
表达式:给出偏移地址的值
DATA SEGMENT
X1 DW 20H,60H,
ORG 100H ;X2的偏移地址为100H
X2 DB 10H,20H,30H
DATA ENDS
CODE SEGMENT
ORG 200H ;使代码段的起始偏移地址为200H
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA ;该代码的起始偏移地址为200H
...
...
...
CODE ENDS
另外在汇编语言中经常可使用地址计数器的值 “$” 来保存正在汇编的指令地址。
如,表示从当前地址跳过6个字节的定位伪指令语句为ORG $ +6
######(3)程序结束伪指令语句
指令格式:
END 标号名
功能:标记汇编语言的源程序结束,汇编程序一碰到END语句就停止汇编
标号名:该程序中第一条可执行语句的标号名,可以默认,若一个程序包含多个模块,END后面带的标号为主程序模块中的标号名称。注意该标号是程序开始执行的起始地址。
注意:若没有用 ORG 指定代码段首地址,则程序从 END 后的标号名所指的地址开始执行,若用 ORG 指定了首地址,则从该首地址开始执行。
CODE SEGMENT
MOV AX,BX
START: MOV AX,12H ;该程序从 MOV AX,12H 开始执行
....
...
...
CODE ENDS
END START
2.6 方式定义伪指令语句
汇编程序有两种操作方式:8086操作方式 和 80386操作方式
指令格式:
.8086
.386
功能:确定汇编程序的执行方式
8086 默认
386 想用32位寄存器时需加上该伪指令
2.7 结构定义伪指令语句
好像是结构体…
2.7.1 结构定义
指令格式:
结构名 STRUCT
...
... (数据变量序列)
...
结构体 ENDS
功能:把各种不同类型的数据存放在同一数据结构中。使结构中各个变量具有各自的局部偏移量(各变量的第一字节与结构起始地址之间的字节距离)。
注意:
- 结构定义后,在汇编过程中不产生,目标代码,也不分配存储空间。只有在结构体被预置后,才具有确定的存储单元位置。
- 结构体中变量可以有 简单变量,多重变量,字符串变量 和 多重结构
- 结构体中可以有其他结构类型(多重结构)
- 当结构被引用时,不允许对多重变量进行修改
- 允许用同样长度的字符串来修改字符串变量
TSTRU STRUCT
DA1 DB 'SXYZ' ;字符串变量
DA2 DW ? ;简单变量
DA3 DW SEG LP1 ;简单变量
DA4 DW 2 DUP(3) ;多重变量
DA5 DW 5678H,1234H ;多重变量
2.7.2 结构预置(分配内存)
指令格式;
结构变量名 结构名 <元素值,元素值...>
结构变量名 结构体 n DUP(<元素值,元素值...>)
功能:对已经定义的结构分配存储空间和预置(初始化)。
<> :专用运算符,用于元素的值初始化。其内的元素值可以默认,表示不进行修改。
DATA1 TSTRU <> ;只分配存储,不初始化
DATA2 TSTRU <'FROM'> ;只改第一个元素,其后保持不变
DATA3 TSTRU <,7FH,SEH LLL> ;不改第一个元素
DATA4 TSTRU 5 DUP(<'7890',,11H>)
2.7.3 结构使用
指令格式:
结构变量名 · 字段变量
功能:给出在不同结构变量名的结构数据中的变量元素值
对于数组,在字段变量后用中括号 [ ] 给出该结构变量与第一个相同的结构变量之间的字节数
DATA4 · DA1[40] ;表示DATA4 · DA1[40] 与DATA4 · DA1[0] 之间相差40个字节。
2.8 分组伪指令语句
指令格式:
组名 GROUP 段1,段2,...
功能:将段1,段2 等逻辑段放在同一个 64KB 的物理段内,并给它起一个新名字,即组名
注意:
- 段1,段2,…等参数可以来自三方面:
- 由SEGMENT定义的段名
- 变量的段基址
- 标号的段基址
- 多个段合成一组后的组名和段名一样,表示该组的段基址,程序中可以将它作为直接段指或段前缀使用。
- 由若干段组成的一个组,用一个段寄存器为基址,组内各段之间的跳转可以认为是段内跳转。
- 用组内的一个变量,像段寄存器一样:
GROUP1: VAR1
2.9 其他伪指令语句
(1)外部 伪指令语句
当程序包含多个模块时,有些程序数据在各个模块间要相互共享,可使用外部伪指令 PUBLIC 和 EXTRN 来实现。
指令格式:
PUBLIC 名称1,名称2,...
EXTRN 名称1:类型,名称2:类型,...
功能:PUBLIC 用来定义全局标识符
EXTRN 用来指出外部标识符
类型:须与原在其他模块中定义时的类型相同
(2)对准 伪指令语句
指令格式;
EVEN
功能:对准伪指令语句使下一语句的地址调整为偶地址(可以提高字的存取速度)