Files
Operating-System/Experiment/asm-exp/实验六/实验六_宏调用.md
2026-06-25 00:09:09 +08:00

298 lines
5.4 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.
# 实验六:宏调用
## 一、基础性实验
### 实验6_1 宏定义与调用一
#### 实验目的
掌握宏的基本定义和调用方法,理解宏与子程序的区别。
#### 实验内容
定义宏实现字符输出功能。
#### 程序代码
```asm
DATAS SEGMENT
CHAR DB 'A'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
; 宏定义
; 功能:输出一个字符
; 参数DL=字符
OUTPUT MACRO
MOV AH, 02H
INT 21H
ENDM
START:
MOV AX, DATAS
MOV DS, AX
MOV DL, CHAR
OUTPUT
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序分析
1. 宏OUTPUT使用MACRO伪指令定义以ENDM结束
2. 宏调用时直接展开参数通过DL传递
3. 宏与子程序的区别宏在调用处展开子程序需要CALL调用
4. 每次宏调用都会产生一段代码,适合代码量较少的情况
#### 程序结果
运行后,屏幕显示字符'A'
---
### 实验6_2 宏定义与调用二
#### 实验目的
掌握带参数的宏定义方法。
#### 实验内容
定义宏实现数值显示功能。
#### 程序代码
```asm
DATAS SEGMENT
NUM DB 5
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
; 宏定义
; 功能显示数字0-9
; 参数DL=数字
DISP_NUM MACRO
ADD DL, 30H ; 转换为ASCII码
MOV AH, 02H
INT 21H
ENDM
START:
MOV AX, DATAS
MOV DS, AX
MOV DL, NUM
DISP_NUM
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序分析
1. 宏DISP_NUM带有参数DL
2. 宏展开时,参数被替换到相应位置
3. ADD DL,30H将数字转换为ASCII码
4. 适合需要多次调用相同功能的情况
#### 程序结果
运行后,屏幕显示数字'5'
---
## 二、加强性实验
### 实验6_3 宏嵌套调用
#### 实验目的
掌握宏的嵌套调用,理解宏展开的机制。
#### 实验内容
定义多个宏,实现复杂的输出功能。
#### 程序代码
```asm
DATAS SEGMENT
MSG DB 'Test$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
; 宏定义:输出字符
PRINT_CHAR MACRO CHAR
MOV DL, CHAR
MOV AH, 02H
INT 21H
ENDM
; 宏定义:换行
NEWLINE MACRO
MOV DL, 0AH
MOV AH, 02H
INT 21H
MOV DL, 0DH
MOV AH, 02H
INT 21H
ENDM
; 宏定义:显示字符串
PRINT_STR MACRO STR
LEA DX, STR
MOV AH, 09H
INT 21H
ENDM
START:
MOV AX, DATAS
MOV DS, AX
PRINT_CHAR 'H'
PRINT_CHAR 'e'
PRINT_CHAR 'l'
PRINT_CHAR 'l'
PRINT_CHAR 'o'
NEWLINE
PRINT_STR MSG
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序分析
1. 定义了三个宏PRINT_CHAR、NEWLINE、PRINT_STR
2. PRINT_CHAR接受参数CHAR用于输出单个字符
3. NEWLINE宏内部调用了两次INT 21H实现换行功能
4. PRINT_STR宏使用LEA指令获取字符串地址
5. 每次宏调用都会产生展开代码
#### 程序结果
运行后,屏幕显示:
```
Hello
Test
```
---
### 实验6_4 宏与子程序比较
#### 实验目的
理解宏与子程序的区别和各自适用场景。
#### 实验内容
通过同一功能分别用宏和子程序实现,对比两者区别。
#### 程序代码
```asm
DATAS SEGMENT
MSG1 DB 'Macro Test$'
MSG2 DB 'Subroutine Test$'
DATAS ENDS
STACKS SEGMENT
DB 64 DUP(?)
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES, DS:DATAS, SS:STACKS
; 宏定义
PRINT_STRING MACRO STR
LEA DX, STR
MOV AH, 09H
INT 21H
ENDM
; 子程序定义
PRINT_PROC PROC
LEA DX, MSG2
MOV AH, 09H
INT 21H
RET
PRINT_PROC ENDP
START:
MOV AX, DATAS
MOV DS, AX
; 使用宏
PRINT_STRING MSG1
MOV DL, 0AH
MOV AH, 02H
INT 21H
; 使用子程序
CALL PRINT_PROC
MOV AH, 4CH
INT 21H
CODES ENDS
END START
```
#### 程序分析
1. 宏在调用处展开,节省调用开销,但代码膨胀
2. 子程序代码独立存在节省存储空间但需要CALL/RET调用开销
3. 宏适合代码量小、调用频繁的情况
4. 子程序适合代码量大、调用次数少的情况
5. 宏的参数传递通过文本替换实现,子程序通过寄存器或堆栈传递
#### 程序结果
运行后,屏幕显示:
```
Macro Test
Subroutine Test
```
---
## 思考题
1. 宏与子程序的主要区别是什么?
- 宏在调用处展开,代码膨胀;子程序独立存在,节省空间
- 宏不需要CALL/RET节省调用开销子程序需要调用开销
- 宏参数传递通过文本替换;子程序通过寄存器或堆栈传递
- 宏适合简短代码多次调用;子程序适合较长代码少次调用
2. 宏定义的优点有哪些?
- 代码可读性好,程序结构清晰
- 参数传递灵活方便
- 无调用开销,执行效率高
- 便于程序的修改和维护
3. 如何选择使用宏还是子程序?
- 代码量小、调用频繁:选择宏
- 代码量大、调用次数少:选择子程序
- 需要递归调用:必须使用子程序
- 需要节省存储空间:选择子程序
---
## 实验总结
1. 宏使用MACRO伪指令定义以ENDM结束
2. 宏调用时直接展开,不占用运行时间
3. 宏参数传递方便,适合少量代码的重复使用
4. 宏会增加代码长度,但不占用存储空间(运行时)
5. 子程序节省存储空间但需要CALL/RET开销
6. 选择宏还是子程序应根据代码量、调用次数和存储空间需求决定