第 4 章 8086 汇编语言程序设计
1. 汇编语言的源程序
(1)编译平台的作用
- 自动分配地址
- 自动进行数值转化
- 语法检查
(2)汇编语言源程序的结构
汇编语言源程序通常由一个或几个程序模块组成,每个模块一般由三个逻辑段组成:
- 数据段 —— 存放数据、变量
- 堆栈段 —— 堆栈区域
- 代码段 —— 存放程序指令
EXE 模板:
(3)8086 汇编语言的语句
汇编语言由指令性语句和指示性语句组成:
- 指令性语句(真指令):汇编时生成机器码。
- 指示性语句(伪指令):汇编时不生成机器码。
2. 8086 汇编中的伪指令
(1)符号定义语句
等值语句(全局)
格式: 符号名 EQU 表达式
eg. PORT EQU 123
等号语句(局部)
格式: NUM = …
注意: 用 EQU 定义的符号未清除前,不能重新定义;用 “=” 定义的符号可在任何时候进行重定义。
(2)变量定义语句
格式: 符号名 DB/DW/DD 表达式
功能: 定义一变量,并为其分配一定数量的存储单元。
定义一组数据
eg. BUFF DW 1234H,8EH
定义一个字的变量,1234H 中 12 放到高地址,34 放到低地址;由于定义的是一个字,8EH 会变成 008EH ,其中 00 放到高地址,8E 放到低地址。
定义一串字符
eg. (考点)
S1 DB ‘AB’ 是定义一个字节,即 S1 = 41 , 42H
S2 DW ‘AB’ 是定义一个字,即 S2 = 4241H ,将 A 放到高地址。
定义保留存储单元
eg. SUM DW ?,?(SUM 偏移地址开始,4 个单元保留)
操作数 ?用来保存存储空间,但不存入数据
复制操作 —— DUP
eg. ALL_ZERO DB 5 DUP(0) 等价于 ALL_ZERO DB 0,0,0,0,0
(3)段定义语句
段定义
段名 SEGMENT [定位类型] [组合方式] [类别]
<汇编语言语句>
段名 ENDS
注意: 两个伪指令总是成对出现,前者说明一个段的开始,后者说明一个段的结束。
段假设
eg. ASSUME CS : code , DS : data , SS : stack
上面语句意思是,CS 将指向名字为 code 的代码段,DS 和 SS 将指向名字为 data/stack 的段。
段赋值
确定基址,但是 CS 不能赋值。
eg. MOV AX , DATA ; MOV DS , AX
段结束
END 标号名
标记汇编源程序的结束,汇编到此停止汇编。
3. DOS 功能调用
(1)键盘输入 —— 1 号调用
格式:
MOV AH , 1
INT 21H
功能: 等待键盘输入一个字符并将输入的字符的 ASCII 码送入 AL 中,同时在显示器上显示该字符。
(2)显示单个字符 —— 2 号调用
格式:
MOV AH , 2
MOV DL , 带显示字符的 ASCII 码
INT 21H
功能: 将 DL 中的字符显示出来。
(3)显示字符串 —— 9 号调用
格式:
LEA DX , 字符串首偏移地址
MOV AH , 9
INT 21H
功能: 显示当前数据区中以 $ 结尾的字符串。
(4)过程终止 —— 4CH 号调用
格式:
MOV AH , 4CH
INT 21H
功能: 结束当前程序。
4. 数据项及表达式
(1)常用运算符
算术运算符 —— + 、- 、* 、/ 、MOD
eg. MOV AX , 4 * 1024 汇编后 MOV AX , 4096
逻辑运算符 —— AND 、OR 、XOR 、NOT
eg. MOV CL , 36H AND 0FH 汇编后 MOV CL , 06H
考点: 不要把逻辑运算符与逻辑运算指令混淆。
eg. AND AX , 3FC0H AND 0FF00H
汇编后源操作数被翻译为 3F00H ,所以上述指令与 AND AX , 3F00H 等价。
关系运算符 —— EQ 、NE 、LT 、GT 、LE 、GE
关系运算的结果是一个逻辑值:真或假
关系为真,结果为全 1 ,关系为假,结果为全 0 。
eg.
MOV AX , 4 EQ 3 ; MOV AX , 0
MOV AX , 4 NE 3 ; MOV AX , 0FFFFH
(2)其它操作符
分析操作符
SEG 操作符
eg. MOV AX , SEG BUFF
OFFSET 操作符
eg. MOV BX , OFFSET BUFF
考点(以下指令的异同):
MOV BX , OFFSET BUFF
LEA BX , BUFF
上面前者是汇编时将偏移地址赋值给 BX ,而 LEA 是在 CPU 执行时才赋值。
eg. BUFF DB 01H , 02H , 03H
① MOV AX , BUFF (×) BUFF是三个字节,不能赋给两个字节的 AX
② MOV AL , BUFF ; MOV AL , BUFF[1]
前者是将 BUFF 得第一个字节赋值给 AL ,后者是将第二个字节赋值给 AL
③ LEA BX , BUFF ; MOV AL , [BX] ; MOV AK , [BX+1]
更推荐上面这些表达方式。
综合运算符
功能: 用于指定其后储存器操作数的类型。
PTR 运算符
格式:<类型> PTR <地址操作数>
类型包含 BYTE , WORD , DWORD , NEAR , FAR
eg. 假设 VAR 定义字变量
MOV AL , VAR
MOV AL , BYTE PTR VAR
ORG 伪指令
ORG 规定了段内的指令或数据存放的开始地址(偏移地址的初值),从此地址起连续存放程序或数据。
格式: ORG <表达式>
eg. OEG 100H
地址计数器 $
这个是汇编程序专门设置的一个表示当前位置的计数器,正常情况下,汇编没扫描一个字节,位置计数器的值便加 1 。
语句:
ARRAY DW 1234H , 5678H
COUNT EQU $ - ARRAY
含义: COUNT 值就是 ARRAY 中数据所占的字节数。
语句:
JMP $
含义: 程
5. 过程定义和宏定义伪指令(中断)
(1)过程定义语句
过程(子程序):一段具有特定功能的,供其它程序调用的公用程序。
(2)调用 CALL
CALL 指令完成调用子程序的功能。
CALL 指令将程序的返回地址(CALL 的下一条指令地址)压入堆栈中保存。断点保护,自动执行。
如果是进调用则将目标的偏移地址等于 IP ,若为远调用则再将目标的段地址等于 CS ,寻址和 JMP 相同。
如果是近调用,则堆栈中只保存返回地址的偏移地址;若是远调用,则还必须保存返回地址的段地址。
(3)RET n 指令
在子程序中,最后一条指令必须返回指令 RET ,它将堆栈中保存的返回地址自动弹出至 CS 和 IP 。
返回地址弹出后,它使 SP 值在正常返回之后的基础上再加上 n(n 为偶数)。
(4)子程序设计
重点:
断点保护通过调用CALL指令,返回RET指令自动执行。(断点保护,自动运行)
调用前要预先确定子程序中要使用哪些寄存器,并定义入口参数和出口参数。参数传递可利用寄存器、存储单元或堆栈(要用BP寻址)
进入子程序后首先要保护主程序的运行状态,保护子程序使用的非参数寄存器(包括标志位) (称为保护现场),退出子程序前要恢复现场。(现场保护,手动运行)
(5)宏定义伪指令
【格式】
宏定义与子程序的区别:宏定义是拿空间换时间。
(6)中断指令和中断返回指令
8086/8088 CPU 在程序中允许安排一条中断指令来引起一个中断过程,这种中断叫内部中断,或叫软中断。被中断的指令地址处称为断点。
INT n
中断的分类:
INT 0 - INT 4 :专用中断
INT 5 - INT 31H :备用中断
INT 32 - INT 0FFH :用户中断
入口地址
格式: INT n
入口地址的地址: n × 4
中断和子程序的区别:
1、中断里入口地址是固定的。
2、中断里 FR 是自动保护,而子程序是需要手动。
3、中断的事件是随机发生的,而子程序是调用发生的。
6. 汇编语言程序设计
(1)常用汇编语言程序框架 (考点):
(1)汇编语言程序设计基本步骤(汇编面试高频题)
1、分析问题,确定模型
2、确定算法
3、绘制流程图 → 程序结构
4、编写程序
5、检查和调试