Files
Operating-System/8086/Exam/第4章 汇编语言及其程序设计(6-8节).md
2026-06-29 21:12:21 +08:00

285 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 4 章 汇编语言及其程序设计6-8 节)总结
> 本章 6-8 节内容重点:**伪指令**4.6)、**汇编语言源程序的结构**4.7)、**汇编语言程序设计**4.8,含顺序/分支/循环/子程序)。与第 4 章前 5 节(指令系统)衔接,但侧重点转向**汇编源程序组织与结构化程序设计**。
---
## 一、详细内容分析
### 4.6 伪指令
伪指令是给汇编程序编译器的指示CPU 不执行,**不产生目标代码**(宏指令除外)。用于选择处理器、定义数据、分配存储区等。
#### 1. END — 源程序结束伪指令
- **格式**`END [标号]`
- **功能**:表示源程序结束,不可缺,是源程序编译的最后一条语句。
- **说明**
1) 标号指示程序开始执行的起始地址;
2) 起始执行地址缺省值为代码段第一条指令地址;
3) 多个模块链接时,主程序用标号,其他程序不用。
#### 2. SEGMENT 和 ENDS — 段定义伪指令
- **格式**
```
段名 SEGMENT [定位类型][组合类型][字长类型]['类别']
段名 ENDS
```
- **功能**:定义段名、段属性,并表示段的开始位置、结束位置。
- **说明**
1) `SEGMENT` 和 `ENDS` 必须成对出现;
2) 段名是段的标识符(基址),由程序员指定;
3) 四个参数选项可省略,使用默认值:
- **定位类型**`BYTE`、`WORD`、`DWORD`、`PARA`(默认)、`PAGE`
- **组合类型**`PUBLIC`、`STACK`、`COMMON`、`MEMORY`、`PRIVATE`(默认)、`AT 表达式`
- **字长类型**`USE16`(默认)、`USE32`
- **类别**`'DATA'`、`'CODE'`、`'STACK'`、`'EXTRA'` 等,连接时同类别段放在连续存储空间。
#### 3. ASSUME — 段分配伪指令
- **格式**`ASSUME 段寄存器名:段名, 段寄存器名:段名, ……`
- **功能**:说明某个段关联哪一个段寄存器。
- **说明**
1) 程序段必须用 CS堆栈段必须用 SS
2) 该语句一般放在代码段最前面;
3) **说明性语句**,除 CS 由初始化赋值外,其他段寄存器在程序中赋值。
#### 4. ORG — 起始地址定义
- **格式**`ORG 数值表达式`
- **功能**:定义指令或数据的起始地址,`$ ← 表达式的值`。数值表达式范围 0~65535。
- **地址计数器 `$`**:指示当前语句使用的段内偏移值,每段开始时为 0每分配一个单元加 1。
#### 5. EVEN — 偶数地址定义
- **格式**`EVEN`
- **功能**:使下一个变量或指令从偶地址开始(用于字访问对齐)。
#### 6. 数据定义伪指令
- **格式**`[变量名] 操作符, 操作数[, …] [: 注释]`
- **功能**:为操作数分配存储单元,用变量与存储单元相联系。
- **操作符**(定义数据类型):
- `DB`1 字节8 位),字节变量;
- `DW`1 字16 位),字变量;
- `DD`1 双字32 位),双字变量。
- **操作数**:常数、表达式、字符串、`?`、`n DUP(操作数)`(重复 n 次)。
- **典型示例**
```
ORG 200H
DATA1 DB 12H, ?, 2+6 ; 12H、保留、08H
EVEN
DATA2 DW 789AH, 5 ; 字变量
DATA3 DD 12345678H ; 双字
DATA4 DW $, 6699H ; $ 为当前地址
DATA5 DB 4 DUP(?) ; 预留 4 个字节
```
#### 7. PROC 和 ENDP — 过程定义伪指令
- **格式**
```
过程名 PROC [属性]
过程名 ENDP
```
- **功能**:定义子程序结构,过程名是入口,是 `CALL` 的操作数。
- **属性**`FAR`、`NEAR`(默认)。
#### 8. EQU — 赋值伪指令
- **格式**`符号常数名 EQU 表达式`
- **功能**:将表达式的值赋给符号常数;**只能定义一次**。
- 例:`DATA1 EQU 88`、`AAA1 EQU CX`、`DATA2 EQU DATA1+12`。
#### 9. 返回值运算符
| 运算符 | 含义 |
|--------|------|
| `SEG 变量/标号` | 段地址值 |
| `OFFSET 变量/标号` | 偏移量值 |
| `TYPE 变量` | 数据类型字节数:`DB=1`、`DW=2`、`DD=4` |
| `TYPE 标号` | 标号属性:`NEAR=-1`、`FAR=-2` |
| `LENGTH 变量` | 第一个数占用的单元数 |
| `SIZE 变量` | 第一个数占用的字节数 |
#### 10. PTR — 临时改变类型属性运算符
- **格式**`类型 PTR 变量/标号`
- **变量类型**BYTE / WORD / DWORD / FWORD / QWORD / TBYTE
- **标号类型**NEAR/ FAR
- 当指令中操作数类型不明确(如 `MOV BYTE PTR [BX], 8` 或 `MOV WORD PTR [BX], 8`)时**必须使用 PTR**。
---
### 4.7 汇编语言源程序的结构
#### 80x86 汇编语言源程序结构特点
1. 一个程序由若干**逻辑段**组成,各逻辑段由伪指令语句定义和说明;
2. 整个源程序以 `END` 伪指令结束;
3. 每个逻辑段由语句序列组成,语句可以是:
- **指令语句**CPU 指令,可执行,汇编时翻译成目标码;
- **伪指令语句**CPU 不执行,提供汇编信息,不产生目标代码;
- **宏指令语句**:一个指令序列,汇编时产生对应的目标代码序列;
- **注释语句**:以分号 `;` 开始,说明性语句,汇编程序不处理;
- **空行语句**:仅包含回车换行符,便于阅读。
4. 每个源程序应当有**返回操作系统的指令语句**(典型:`MOV AH,4CH` + `INT 21H`),使程序执行完后能自动返回系统。
#### DOS 环境下两种程序结构
| 类型 | 长度限制 | 加载特点 | 段起始 | 适用场景 |
|------|----------|----------|--------|----------|
| **.COM 文件** | 一个段长64KB | 无段重定位,结构紧凑、装入快 | 偏移量从 100H 开始,且 100H 处必须是可执行指令 | 小型程序 |
| **.EXE 文件** | 仅受内存空间限制 | 需段重定位,占用盘空间大、装入慢 | 由程序员指定 | 中、大型程序 |
---
### 4.8 汇编语言程序设计
#### 基本步骤
1. 描述问题 → 2. 确定算法 → 3. 绘制流程图 → 4. 分配存储空间和工作单元 → 5. 编写程序 → 6. 上机调试。
#### 程序基本结构形式:顺序、分支、循环、子程序。
#### 4.8.1 分支程序设计
- **分支程序**:根据不同情况或条件执行不同功能,具有判断和转移功能,利用条件转移指令对状态标志进行判断实现转移。
- **特点**:按条件判断、转移、分支。
- **两种结构****二路分支**if-then-else、**多路分支**case
- **共同特点**:在某一特定条件下,只执行多个分支中的一个。
#### 4.8.2 循环程序设计
- **循环程序五部分**
1. 初始化部分(设置初值);
2. 循环工作部分(核心);
3. 循环修改部分(修改工作变量、指针);
4. 循环控制部分(修改控制变量,确定程序走向);
5. 循环结束部分(结果处理)。
- **两种常用结构**
- **先执行后判断**DO-WHILE至少执行一次循环体
- **先判断后执行**DO-UNTIL允许零次循环。
#### 典型例题:例 4.8.4 多重循环(冒泡排序)
- **问题**:从首地址 `AA1` 开始存放 N 个无符号字节数据,用**冒泡法**将数据按由大到小排序。
- **冒泡法核心**相邻两个单元比较位置交换N-1 次后排出一个最大(或最小)数据;经 N-1 次循环完成排序。
- **关键步骤**:比较 → 判断 → 交换。
**版本 (1)N-1 遍,每遍比较 N-1 次** — 内外循环计数都用 N-1。
**版本 (2)N-1 遍,每遍比较次数少 1** — 用 DX 作为外循环计数器,每次进入内循环前 `MOV CX, DX`,使每遍比较次数递减。
**版本 (3):有交换标志** — 增加 AH 作为交换标志,每次交换时 `MOV AH,1`;每遍结束 `OR AH,AH` + `JZ` 提前退出;无交换则提前结束排序(效率优化)。
#### 4.8.3 子程序设计
##### 1. 子程序的定义
- **子程序组成 7 部分**:子程序定义(即入口)、保护现场、取入口参数、子程序体、存输出参数、恢复现场、返回。
##### 2. 现场的保存与恢复
- **保护现场**:在子程序中,保护那些主程序要用、而子程序也要用的寄存器内容。
- **恢复现场**:恢复现场保护的内容。
- **方法**(1) 使用堆栈指令PUSH/POP(2) 使用数据传送指令。
##### 3. 子程序的参数传送
- **参数传送**:主程序和子程序之间的数据传送。
- **方法**(1) 通过**寄存器/存储器**传送参数;(2) 通过**堆栈**传送参数或参数表地址。
**(1) 通过寄存器传送参数**(最常用)
- 特点:参数放在寄存器中,简便、实用,适用于参数较少的情况。
**(2) 典型例题:例 4.8.5 — 用寄存器传送,编制键入 5 位十进制数加法程序**
- **子程序 S1 功能**:键盘输入 5 位以内十进制数 → 二进制数 → 存入 CX**用非数字键结束本次数字输入**。
- 10 进制 → 2 进制转换算法(霍纳/秦九韶法):
`((D5×10+D4)×10+D3)×10+D2)×10+D1)×10+D0`
- 实现方式:每按一个数字键,`CX×10 + 本次输入数位`。
- **子程序 S2 功能**CX二进制数 → 十进制数,在显示器上显示。
- 基本方法:从万位开始依次比较 `CX ≥ 10000`、`≥ 1000`、`≥ 100`、`≥ 10`,不够则跳过(避免最高位显示 0用 `SUB` + `INC DL`(不影响 CF+ `JNC` 累加,再用 `OR DL,30H` 转为 ASCII 码,最后用 `INT 21H` 的 02H 号功能逐位显示。
- **主程序 MAIN**:调用 S1 取被加数和加数 → 求和 → 调用 S2 显示结果。
- 约束条件:结果 ≤ 65535MAIN、S1、S2 同段,子程序使用 NEAR 属性,主程序 MAIN 使用 FAR 属性。
- **程序返回操作系统**`MOV AH, 4CH` + `INT 21H`。
---
## 二、考点总结
### 1. 伪指令4.6
- 【高频】**END**:源程序结束伪指令,必须有,可带启动标号。
- 【高频】**SEGMENT/ENDS**成对出现四个参数定位、组合、字长、类别及默认值PARA / PRIVATE / USE16
- 【高频】**ASSUME**说明段与段寄存器关联CS、SS 必用,其他由程序赋值),属说明性语句。
- 【高频】**数据定义 DB/DW/DD**:字节/字/双字,`DUP(?)` 预留空间;`?` 表示不赋值。
- 【高频】**ORG** 与 **`$` 地址计数器**:控制起始地址。
- **EQU**:赋值伪指令,**只能定义一次**,可指向寄存器名。
- **PROC/ENDP**:过程定义,属性 NEAR默认/ FAR过程名是 CALL 的操作数。
- 【高频】**PTR**:类型不确定时必须使用(如 `MOV BYTE PTR [BX], 8`)。
- **返回值运算符**SEG / OFFSET / TYPE / LENGTH / SIZE 的返回值含义TYPE: NEAR=-1、FAR=-2、DB=1、DW=2、DD=4
### 2. 源程序结构4.7
- 【高频】**5 种语句类型**:指令语句、伪指令语句、宏指令语句、注释语句、空行语句。
- 【高频】**.COM 与 .EXE 比较**段长限制64KB / 内存空间、段重定位、入口偏移100H / 段首)。
- 程序结尾必须有返回 DOS 指令:`MOV AH,4CH` + `INT 21H`。
### 3. 程序设计4.8
- **程序设计 6 步**:描述问题 → 算法 → 流程图 → 存储分配 → 编写 → 调试。
- **基本结构 4 类**:顺序、分支、循环、子程序。
- 【高频】**分支**二路分支、多路分支常用条件转移指令JZ/JNZ、JC/JNC、JO/JNO 等)。
- 【高频】**循环 5 部分**:初始化、工作、修改、控制、结束。
- 【高频】**两种循环结构**:先执行后判断(至少一次)、先判断后执行(可零次)。
- 【高频】**冒泡排序**N 个数需 N-1 遍,每遍两两比较交换;可优化为带"交换标志"提前退出。
- 【高频】**子程序 7 部分**及**参数传送两种方式**:寄存器传送(最常用)、堆栈传送。
- **现场保护**PUSH/POP 配对使用,后进先出。
### 4. 常见题型
| 题型 | 示例 |
|------|------|
| **简答题** | 简述汇编语言源程序的 5 种语句;简述子程序的组成结构;简述现场保护与恢复的方法 |
| **填空题** | `DB`/`DW`/`DD` 数据类型字节数SEGMENT 默认定位类型 PARATYPE NEAR = -1 |
| **选择题** | 下列伪指令属于说明性语句的是A. END B. ASSUME C. DB D. PROCCOM 文件入口偏移为 100H |
| **判断题** | SEGMENT 与 ENDS 必须成对出现EQU 可重复定义同一符号×PROC 默认属性 FAR×应为 NEAR |
| **程序阅读/改错** | 阅读冒泡排序程序指出错误(如 LOOP 用错、循环计数初值错) |
| **程序设计题** | 用寄存器传送参数设计"键入十进制数求和并显示"程序;用多重循环实现数据排序 |
| **指令正误** | `MOV BYTE PTR [BX], 8` 是否合法(合法);`MOV AH, 4CH` 与 `INT 21H` 是否配套(是) |
### 5. 易混淆点
- **PROC 属性**:默认 **NEAR**,不是 FAR只有跨段调用才用 FAR。
- **ASSUME**:仅说明关联关系,**不是赋值**;段寄存器 DS、ES 等需程序中 `MOV`。
- **PTR 与变量定义**DB 定义字节变量,若要按字读需 `MOV AX, WORD PTR DATA2`。
- **冒泡排序方向**:从大到小排序时用 `JNC`(前大后小不交换);从小到大排序时用 `JC`(前小后大不交换)。
- **EQU vs `=`**EQU 不允许重复定义同名符号。
- **堆栈段**:必须有 `SEGMENT … STACK`,并通过 `ASSUME SS:段名` 关联。
### 6. 综合程序设计模板(务必熟记)
```
DATA SEGMENT
; 数据定义
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
MAIN PROC FAR
MOV AX, DATA
MOV DS, AX
; … 程序主体 …
MOV AH, 4CH
INT 21H
MAIN ENDP
; … 子程序 …
CODE ENDS
END MAIN
```