汇编语言程序格式
逻辑段
- 汇编语言源程序由一个或多个逻辑段组成
- 一个程序中可以有几个同一类型的逻辑段
- 必须至少有一个代码段
[!注] 源程序分段的目的在于程序结构清晰、便于内存分配,寻址方便,一个源程序需要设置几个段应该根据具体问题来定 - 逻辑段: - 程序段 - 主要由指令语句组成,完成源程序的功能 - 数据段 - 定义数据及符号的伪指令组成 - 附加段 - 定义数据及符号的伪指令组成 - 堆栈段 - 定义堆栈伪指令组成 - 段定义伪操作:
- 如果不指定,则采用默认参数 - 段名对外表现为立即数,为该段的的地址 - 语句格式:
常数和表达式
- 常数:表示一个固定的值
- 十进制常数:d或缺省
- 十六进制:h
- 二进制:b
- 八进制:q
- 字符串常数:ASCII码
- 符号常数:
- 等价EQU伪指令:
符号名 EQU 数值表达式
符号名 EQU 字符串
- 等号=伪指令
符号名=数值
- 二者的区别:后者可使用多次,前者只能使用一次
- 等价EQU伪指令:
- 数值表达式:使用常数、符号常数和算数、逻辑、关系运算符组成的表达式\((75*2+X)/Y\)
- 表达式:
- 汇编程序在汇编过程中计算表达式,最终得到一个数值
- 一个常数或一个地址
- 程序运行之前,就已经计算出了表达式
- 因此,程序的运行速度没有变慢,并且增加了程序的可读性
- 汇编程序在汇编过程中计算表达式,最终得到一个数值
变量和标号
- 变量
- 数据单元的符号地址
- 书写格式:不能使用系统保留字、不能以数字开头
- 变量的定义:用[[汇编语言程序格式#^2eea09|数据定义伪指令]]来定义
- 标号
- 一个指令单元的符号地址
- 书写格式:不能使用系统保留字、不能以数字开头
- 定义:在一条指令语句前输入标号且用
:
隔开
- 变量定义伪指令: ^2eea09
- 格式:
变量 DB/DW/DD/DF/DQ/DT 操作数1,....,操作数n
- 功能:
- 定义变量
- 在内存中分配一组存储单元
- 对单元进行初始化
- 分类:
- 格式:
- 操作数:
- 一组常数或数值表达式
DATA DB 2, 100*2-5,0,-1
- 一组字符串
STRING DB 'This is a string'
- 变量名或标号名
ADDR1 DW BLOCK
:将BLOCK
的偏址放在ADDR1
单元ADDR2 DD BLOCK
:将BLOCK
的偏址和段地址放在ADDR2
四字节单元中
?
- 只分配空间,但不进行初始化,其中的值为随机值
- 重复
DUP
语句- 格式:
重复数 n dup (重复内容)
- 功能:重复
- 例:
BLOCK DB 3 DUP (0,1,-1)
- 格式:
- 一组常数或数值表达式
起始地址和对准语句
ORG
- 格式:
ORG 表达式
- 功能:置顶随后指令或定义数据的偏移地址
- 说明:
- 可以设置程序段、数据段的任何位置
- 若没有进行设置,默认的逻辑起始地址为
0000H
- 格式:
EVEN
- 格式:
EVEN
- 偶地址对齐指令,若当前地址是奇数,则+1
- 格式:
ALIGN
- 格式:
ALIGN n
- 功能:使随后的数据或指令起始于
n
(2,4,8)的倍数地址
- 格式:
地址计数器$
汇编器在将原地址转化为目标程序过程中,需要使用地址计数器跟踪其中代码或数据的偏移地址 -
$
表示当前的偏移地址 -$
在程序中的不同位置其值是不同的
地址表达式
- 地址表达式的组成:变量、标号、+、-
- 地址表达式可以相减、而不能相加,相减表示两个地址之间的距离
- 含有变量的地址表达式其类型与该变量保持一致
变量和标号的属性
- 变量的属性:
- 段属性:变量的段地址
- 偏移属性:变量的偏移地址
- 类型属性:变量所指单元的类型(字节、字、双字等)
- 标号的属性:
- 段属性:定义标号所在段的段地址
- 偏移属性:定义标号处到段地址的距离
- 类型属性:NEAR(段内)和FAR(段间)
地址操作符
- SEG
- 格式:
SEG 变量或标号
- 功能:得到操作数所在的段的段首地址
MOV AX, SEG ARR
- 格式:
OFFSET
- 格式:
OFFSET 变量或标号
- 功能:得到操作数所在的偏移地址
MOV AX, OFFSET BUF
- 格式:
类型操作符
- 功能:指定类型
汇编程序编写
stack segment stack
dw 512 dup(?)
stack ends
data segment
... ;在数据段定义数据
data ends
code segment
assume cs:code, ds:data, ss:stack
start:
mov ax, data
mov ds, ax
... ;在代码段填入指令序列
mov ah, 4c00h
int 21h
... ;子程序代码
code ends
end start
段类型说明伪操作
- 在代码段开始必须用ASSUME伪操作声明段和寄存器之间的关系:
ASSUME 段寄存器:段名[,段寄存器:段名,...]
- 通知MASM,建立段寄存器与段的缺省关系
实际上,数据段之所以称为数据段,是由于DS指向它。 由于程序运行时可以改变DS的值,使任何段都可以称为数据段
- ASSUME语句必须位于程序段开始的位置