# 汇编语言程序开发
# 汇编语言程序的语句格式
# 硬指令 & 执行性语句
硬指令:使 CPU 产生动作、并在程序执行时才处理的语句
执行性语句 —— 表达处理器指令,由硬指令构成的语句,它通常对应一条机器指令,出现在程序的代码段中,格式:
1 | 标号: 硬指令助记符 操作数,操作数,... ;注释 |
标号:反映硬指令位置(逻辑地址)的标识符,后跟一个冒号分隔
硬指令助记符:可以是任何一条处理器指令
处理器指令的操作数可以是立即数、寄存器和存储单元
# 伪指令 & 说明性语句
伪指令 —— 不产生 CPU 动作、在程序执行前由汇编程序处理的说明性语句。伪指令与具体的处理器类型无关,但与汇编程序的版本有关
说明性语句 —— 由伪指令构成的语句,它通常指示汇编程序如何汇编源程序:
1 | 名字 伪指令助记符 参数,参数,... ;注释 |
名字:反映伪指令位置(逻辑地址)和属性的标识符,后跟空格或制表符分隔,没有冒号
伪指令助记符:定义字节数据和字符串的 DB 就是伪指令
伪指令的参数可以是常数、变量名、表达式等,可以有多个,参数之间用逗号分隔
# 标识符
标号和名字是符合汇编程序语法的用户自定义的标识符
标识符一般最多由 31 个字母、数字及规定的特殊符号(如 _、$、?、@)组成,不能以数字开头。默认情况下,汇编程序不区别标识符中的字母大小写。一个程序中,每个标识符的定义是唯一的,还不能是汇编语言采用的保留字。
保留字是汇编程序已经利用的标识符,主要有:
- 硬指令助记符 —— 例如:
MOV、ADD
- 伪指令助记符 —— 例如:
DB、EQU
- 操作符 —— 例如:
OFFSET、PTR
- 寄存器名 —— 例如:
AX、CS
# 汇编语言源程序框架
# 简化段定义的源程序框架
1 | .model small ;存储模型伪指令.model,small表示小型模式 |
MASM 5.0/5.1 不支持 .startup
和 .exit
,可修改如下
1 | .model small ;存储模型伪指令.model,small表示小型模式 |
# 完整段定义的源程序框架
1 | stack segment stack |
# 汇编语言程序的开发过程
# DOS 系统功能调用
DOS 系统主要分配 21H 号中断,用于程序员调用 DOS 操作系统工功能
- 中断调用指令:
INT 21H
在 AH 寄存器中设置系统功能调用号
# 字符输入 (01H)
从键盘读入一个字符,并使用 AL 保存出口参数
1 | MOV AH,01H |
# 字符输出 (02H)
在显示器当前光标位置显示给定字符,且光标右移一个字符位置,使用 DL 作为入口参数
1 | MOV AH,02H |
# 字符串输入 (0AH)
需要事先在主存设置用于保存输入字符串的缓冲区,使用 ** DS:DX
作为出口参数 **
- 缓冲区的第 1 字节填入最多欲接收的字符个数(包括回车符)
- 缓冲区的第 2 个字节存放实际输入的字符个数(不包括回车符)
- 从第 3 个字节开始存放输入的字符串,实际输入字符数多余定义数时,多出的字符被丢弃
1 | buffer db 81 ;可能输入的最大字符数 |
# 字符串输出 (09H)
需要事先将欲显示的字符串保存在主存中
- 设置 ** 入口参数
DS:DX
** 等于该字符串在主存中的首地址 - 字符串必须以
$(24H)
结束
1 | string db 'hello,everybody','$' |
# 按键判断 (0BH)
仅判断当前是否有按下的键,设置输出参数 AL 后退出。
AL = 0
没有按键AL = FFH
已经按键
# 参数 & 变量 & 标号
# 数值型参数
# 常数
十进制常数 – 以 D/d 结尾,默认情况后缀可省略
十六进制常数 – 以 H/h 结尾
八进制 – 以 Q/q 结尾
二进制 – 以 B/b 结尾
字符串常数 – 用英文缩略号括起来的单个字符或多个字符
符号常数 – 利用一个标识符表达一个数值。符号定义伪指令有 EQU 和 **=**
1 | 符号名 equ 数值表达式 |
EQU 用于数值等价时不能重复定义符号名,但是 "=" 允许重复赋值
1 | eg: |
# 数值表达式
算术运算符: +,-,*,/,mod
逻辑运算符: and,or,xor(异或),not
移位运算符: shl,shr
关系运算符: eq,ne,gt(大于),lt(小于),ge(大于等于),le(小于等于)
- 用 FFFFH (补码 - 1) 表示真
- 用 0000H 表示假
1 | eg: |
高低分离符: high(高字节), low(低字节), highword(高字),lowword(低字)
1 | mov ah, high 8765h |
# 变量定义伪指令
格式
1 | 变量名 伪指令 初值表 |
-
变量名:用户自定义的标识符,表示初值表首元素的逻辑地址。变量名可以没有,在此情况下直接为初值表分配空间,无符号地址
-
初值表:用 "," 分隔的参数,主要由数值常数、表达式、"?","DUP" 组成
- "?" 表示初值不确定
- 重复初值可以用 DUP 进行定义
1 | 重复次数 dup(重复参数) |
- 变量定义伪指令有
DB、DW、DD、DF、DQ、DT
# 定义字节单元伪指令 DB
用于分配一字节或多字节单元,初值表中的每个数据一定是字节量 (Byte),可以是 的无符号数,或 带符号数
1 | .data |
存储单元 | 偏移地址 |
---|---|
43h© | 0007H |
42h(B) | 0006H |
41h(A) | 0005H |
——(?) | 0004H |
64h(100) | 0003H |
64h(100) | 0002H |
fbh(-5) | 0001H |
61h(a) | 0000H |
# 定义字单元伪指令 DW
用于分配一个或多个字单元,初值表中的每个数据一定是字量 (Word),一个字单元可用于存放任何 16 位数据,如:一个段地址、一个偏移地址、两个字符、 之间的无符号数、 之间的带符号数
1 | wnum equ 5678h ;定义wnum为常量 |
-
变量实质表达的是主存地址
-
仅使用变量名或者加个常量是直接寻址
-
再加一个寄存器是寄存器相对寻址
-
加两个寄存器是基址变址相对寻址
# 定义双字单元伪指令 DD
用于分配一个或多个双字单元,初值表中的每个数据一定是一个 32 位的双字量
可以用来表达 16 位段地址和 16 位偏移地址的远指针
# 其他数据定义伪指令 DF&DQ&DT
定义 3 字伪指令 DF:为一个或多个 6 字节变量分配空间及初始化
定义 4 字伪指令 DQ:为一个或多个 8 字节变量分配空间及初始化
定义 10 字节伪指令 DT:为一个或多个 10 字节变量分配空间及初始化
** 练习:** 定义一个缓冲区,包含 33H、34H、35H、36H 四个字节字符,把这四个数据复制 20 遍,存入接着的缓冲区,最后显示出复制结果
1 | source db 33j, 34h, 35h, 36h |
# 定位伪指针 ORG&EVEN&ALIGN
1 |
|
1 |
|
-
type 名字/标号
返回一个字量数值,表明名字或标号的类型;对字节、字、双字变量依次返回 1,2,4