689 lines
11 KiB
Markdown
689 lines
11 KiB
Markdown
# 实验九 BIOS中断实验报告
|
||
|
||
## 一、实验目的
|
||
|
||
1. 掌握BIOS中断调用的基本原理和方法
|
||
2. 学会使用INT 10H进行屏幕显示和图形操作
|
||
3. 学会使用INT 16H进行键盘输入处理
|
||
4. 学会使用INT 1AH读取系统时间和日期
|
||
5. 掌握通过端口操作控制硬件的方法
|
||
|
||
## 二、实验内容
|
||
|
||
### 2.1 基础性实验
|
||
|
||
#### 实验1-1:字符串显示程序
|
||
|
||
**实验题目**:使用INT 10H的13H功能显示字符串
|
||
|
||
**程序源码** (string_display.asm):
|
||
|
||
```asm
|
||
; 实验九 - 字符串显示程序
|
||
; 功能: 使用INT 10H的13H功能在屏幕上显示字符串
|
||
; 模式: 文本模式 80x25 彩色
|
||
|
||
.MODEL SMALL
|
||
.DATA
|
||
MSG DB 'Hello, BIOS Interrupt!', 0DH, 0AH, '$'
|
||
CRLF DB 0DH, 0AH, '$'
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
; 设置光标位置 (0, 0)
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 0
|
||
MOV DL, 0
|
||
INT 10H
|
||
|
||
; 使用INT 10H的13H功能显示字符串
|
||
MOV AH, 13H
|
||
MOV AL, 01H
|
||
MOV BH, 0
|
||
MOV BL, 0FH
|
||
MOV CX, 24
|
||
LEA BP, MSG
|
||
INT 10H
|
||
|
||
MOV AH, 01H
|
||
INT 21H
|
||
.EXIT
|
||
END
|
||
```
|
||
|
||
**说明**:INT 10H的13H功能用于显示带属性的字符串,AL=01H表示字符串包含属性,BL中指定前景色。
|
||
|
||
---
|
||
|
||
#### 实验1-2:键盘输入程序
|
||
|
||
**实验题目**:使用INT 16H读取键盘输入
|
||
|
||
**程序源码** (keyboard_input.asm):
|
||
|
||
```asm
|
||
; 实验九 - 键盘输入程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
PROMPT DB 'Please press any key: ', '$'
|
||
KEY_MSG DB 'You pressed: ', '$'
|
||
CRLF DB 0DH, 0AH, '$'
|
||
BUFFER DB 80 DUP(?)
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
LEA DX, PROMPT
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV AH, 10H
|
||
INT 16H
|
||
|
||
MOV [BUFFER], AL
|
||
MOV [BUFFER+1], AH
|
||
|
||
LEA DX, CRLF
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, KEY_MSG
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV AL, [BUFFER]
|
||
CALL PRINT_CHAR
|
||
|
||
MOV AH, 02H
|
||
MOV DL, ' '
|
||
INT 21H
|
||
|
||
MOV AL, [BUFFER+1]
|
||
CALL PRINT_HEX
|
||
|
||
MOV AH, 00H
|
||
INT 16H
|
||
.EXIT
|
||
|
||
PRINT_CHAR PROC
|
||
PUSH AX
|
||
MOV DL, AL
|
||
MOV AH, 02H
|
||
INT 21H
|
||
POP AX
|
||
RET
|
||
PRINT_CHAR ENDP
|
||
|
||
PRINT_HEX PROC
|
||
PUSH CX
|
||
PUSH DX
|
||
MOV DL, AL
|
||
MOV CL, 4
|
||
SHR DL, CL
|
||
CALL PRINT_NIBBLE
|
||
MOV DL, AL
|
||
AND DL, 0FH
|
||
CALL PRINT_NIBBLE
|
||
POP DX
|
||
POP CX
|
||
RET
|
||
PRINT_HEX ENDP
|
||
|
||
PRINT_NIBBLE PROC
|
||
PUSH DX
|
||
CMP DL, 10
|
||
JB IS_DIGIT
|
||
ADD DL, 'A' - 10
|
||
JMP PRINT_IT
|
||
IS_DIGIT:
|
||
ADD DL, '0'
|
||
PRINT_IT:
|
||
MOV AH, 02H
|
||
INT 21H
|
||
POP DX
|
||
RET
|
||
PRINT_NIBBLE ENDP
|
||
END
|
||
```
|
||
|
||
**说明**:INT 16H的10H功能读取扩展键盘,00H功能读取基本键盘,返回值AL=ASCII码,AH=扫描码。
|
||
|
||
---
|
||
|
||
#### 实验1-3:读取时间程序
|
||
|
||
**实验题目**:使用INT 1AH读取系统时间
|
||
|
||
**程序源码** (read_time.asm):
|
||
|
||
```asm
|
||
; 实验九 - 读取时间程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
TIME_MSG DB 'Current system time: ', '$'
|
||
HOUR_DB '00', ':', '$'
|
||
MIN_DB '00', ':', '$'
|
||
SEC_DB '00', '$'
|
||
CRLF DB 0DH, 0AH, '$'
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
MAIN_LOOP:
|
||
MOV AH, 02H
|
||
INT 1AH
|
||
; DL=日, DH=时, CL=分, CH=秒 (BCD)
|
||
|
||
MOV AL, DH
|
||
CALL BIN_TO_BCD
|
||
MOV [HOUR_DB], AH
|
||
MOV [HOUR_DB+1], AL
|
||
|
||
MOV AL, CL
|
||
CALL BIN_TO_BCD
|
||
MOV [MIN_DB], AH
|
||
MOV [MIN_DB+1], AL
|
||
|
||
MOV AL, CH
|
||
CALL BIN_TO_BCD
|
||
MOV [SEC_DB], AH
|
||
MOV [SEC_DB+1], AL
|
||
|
||
MOV AX, 0600H
|
||
MOV BH, 07H
|
||
MOV CX, 0000H
|
||
MOV DX, 184FH
|
||
INT 10H
|
||
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 10
|
||
MOV DL, 30
|
||
INT 10H
|
||
|
||
LEA DX, TIME_MSG
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, HOUR_DB
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, MIN_DB
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, SEC_DB
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV CX, 0
|
||
MOV DX, 0
|
||
MOV AH, 86H
|
||
INT 15H
|
||
|
||
JMP MAIN_LOOP
|
||
.EXIT
|
||
|
||
BIN_TO_BCD PROC
|
||
PUSH DX
|
||
MOV AH, 0
|
||
MOV DL, 10
|
||
DIV DL
|
||
MOV DL, AH
|
||
MOV AH, AL
|
||
MOV AL, DL
|
||
POP DX
|
||
RET
|
||
BIN_TO_BCD ENDP
|
||
END
|
||
```
|
||
|
||
**说明**:INT 1AH的02H功能返回BCD格式时间,需要转换为ASCII字符串显示。
|
||
|
||
---
|
||
|
||
#### 实验1-4:声音程序
|
||
|
||
**实验题目**:通过端口操作产生声音
|
||
|
||
**程序源码** (sound_porgram.asm):
|
||
|
||
```asm
|
||
; 实验九 - 声音程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
TONE_DB 200, 400, 600, 800, 1000
|
||
COUNT DB 5
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
MOV AL, 10110110B
|
||
OUT 43H, AL
|
||
|
||
LEA SI, TONE_DB
|
||
MOV CL, [COUNT]
|
||
|
||
TONE_LOOP:
|
||
LODSB
|
||
CBW
|
||
|
||
OUT 42H, AL
|
||
MOV AL, AH
|
||
OUT 42H, AL
|
||
|
||
IN AL, 61H
|
||
OR AL, 00000011B
|
||
OUT 61H, AL
|
||
|
||
MOV CX, 0FFFFH
|
||
DELAY1:
|
||
LOOP DELAY1
|
||
|
||
IN AL, 61H
|
||
AND AL, 11111100B
|
||
OUT 61H, AL
|
||
|
||
MOV CX, 0FFFFH
|
||
DELAY2:
|
||
LOOP DELAY2
|
||
|
||
DEC CL
|
||
JNZ TONE_LOOP
|
||
|
||
MOV AH, 01H
|
||
INT 21H
|
||
.EXIT
|
||
END
|
||
```
|
||
|
||
**说明**:通过端口61H控制扬声器,端口42H设置8253计数器2的频率。频率=1193180/计数值。
|
||
|
||
---
|
||
|
||
### 2.2 加强性实验
|
||
|
||
#### 实验2-1:图形显示程序
|
||
|
||
**实验题目**:设置图形模式并画线
|
||
|
||
**程序源码** (graphics_display.asm):
|
||
|
||
```asm
|
||
; 实验九 - 图形显示程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
MSG DB 'Press any key to exit...', '$'
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AH, 00H
|
||
MOV AL, 13H
|
||
INT 10H
|
||
|
||
; 红色水平线
|
||
MOV CX, 20
|
||
MOV DX, 50
|
||
LINE1:
|
||
MOV AL, 0FCH
|
||
MOV AH, 0CH
|
||
INT 10H
|
||
INC CX
|
||
CMP CX, 100
|
||
JNE LINE1
|
||
|
||
; 绿色垂直线
|
||
MOV CX, 150
|
||
MOV DX, 30
|
||
LINE2:
|
||
MOV AL, 3FH
|
||
MOV AH, 0CH
|
||
INT 10H
|
||
INC DX
|
||
CMP DX, 90
|
||
JNE LINE2
|
||
|
||
; 蓝色斜线
|
||
MOV CX, 200
|
||
MOV DX, 100
|
||
LINE3:
|
||
MOV AL, 9FH
|
||
MOV AH, 0CH
|
||
INT 10H
|
||
INC CX
|
||
INC DX
|
||
CMP CX, 260
|
||
JNE LINE3
|
||
|
||
MOV AH, 00H
|
||
MOV AL, 03H
|
||
INT 10H
|
||
|
||
LEA DX, MSG
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV AH, 00H
|
||
INT 16H
|
||
.EXIT
|
||
END
|
||
```
|
||
|
||
**说明**:INT 10H的00H功能设置图形模式13H(320x200x256色),0CH功能在图形模式下画点。
|
||
|
||
---
|
||
|
||
#### 实验2-2:键盘计数器程序
|
||
|
||
**实验题目**:统计按键次数
|
||
|
||
**程序源码** (keyboard_counter.asm):
|
||
|
||
```asm
|
||
; 实验九 - 键盘计数器程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
TITLE_MSG DB '=== Keyboard Counter ===', 0DH, 0AH, '$'
|
||
COUNT_MSG DB 'Key presses: ', '$'
|
||
COUNT_STR DB '00000', '$'
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
MOV AX, 0600H
|
||
MOV BH, 07H
|
||
MOV CX, 0000H
|
||
MOV DX, 184FH
|
||
INT 10H
|
||
|
||
LEA DX, TITLE_MSG
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, COUNT_MSG
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
LEA DX, COUNT_STR
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
XOR CX, CX
|
||
|
||
COUNT_LOOP:
|
||
MOV AH, 01H
|
||
INT 16H
|
||
JZ NO_KEY
|
||
|
||
MOV AH, 00H
|
||
INT 16H
|
||
|
||
CMP AH, 01H
|
||
JE EXIT_PROGRAM
|
||
|
||
INC CX
|
||
CALL WORD_TO_STR
|
||
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 2
|
||
MOV DL, 12
|
||
INT 10H
|
||
|
||
LEA DX, COUNT_STR
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
NO_KEY:
|
||
MOV CX, 0FFFFH
|
||
DELAY:
|
||
LOOP DELAY
|
||
JMP COUNT_LOOP
|
||
|
||
EXIT_PROGRAM:
|
||
.EXIT
|
||
|
||
WORD_TO_STR PROC
|
||
PUSH AX
|
||
PUSH BX
|
||
PUSH DX
|
||
MOV AX, CX
|
||
MOV BX, 10
|
||
MOV DX, 0
|
||
DIV BX
|
||
ADD DL, '0'
|
||
MOV [COUNT_STR+4], DL
|
||
MOV DX, 0
|
||
DIV BX
|
||
ADD DL, '0'
|
||
MOV [COUNT_STR+3], DL
|
||
MOV DX, 0
|
||
DIV BX
|
||
ADD DL, '0'
|
||
MOV [COUNT_STR+2], DL
|
||
MOV DX, 0
|
||
DIV BX
|
||
ADD DL, '0'
|
||
MOV [COUNT_STR+1], DL
|
||
MOV DX, 0
|
||
DIV BX
|
||
ADD DL, '0'
|
||
MOV [COUNT_STR], DL
|
||
POP DX
|
||
POP BX
|
||
POP AX
|
||
RET
|
||
WORD_TO_STR ENDP
|
||
END
|
||
```
|
||
|
||
**说明**:INT 16H的01H功能检查是否有按键(ZF=1表示无按键),00H功能读取按键。
|
||
|
||
---
|
||
|
||
#### 实验2-3:时钟显示程序
|
||
|
||
**实验题目**:实时显示系统时间
|
||
|
||
**程序源码** (clock_display.asm):
|
||
|
||
```asm
|
||
; 实验九 - 时钟显示程序
|
||
.MODEL SMALL
|
||
.DATA
|
||
TIME_FORMAT DB '00:00:00', '$'
|
||
TITLE DB '=== Real Time Clock ===', 0DH, 0AH, '$'
|
||
DATE_FMT DB 'Date: 20XX/XX/XX', '$'
|
||
|
||
.CODE
|
||
.STARTUP
|
||
MOV AX, @DATA
|
||
MOV DS, AX
|
||
|
||
MAIN_LOOP:
|
||
MOV AH, 02H
|
||
INT 1AH
|
||
|
||
MOV AL, DH
|
||
CALL BCD_TO_STR
|
||
MOV [TIME_FORMAT], AH
|
||
MOV [TIME_FORMAT+1], AL
|
||
|
||
MOV AL, CL
|
||
CALL BCD_TO_STR
|
||
MOV [TIME_FORMAT+3], AH
|
||
MOV [TIME_FORMAT+4], AL
|
||
|
||
MOV AL, CH
|
||
CALL BCD_TO_STR
|
||
MOV [TIME_FORMAT+6], AH
|
||
MOV [TIME_FORMAT+7], AL
|
||
|
||
MOV AH, 04H
|
||
INT 1AH
|
||
|
||
MOV AL, CH
|
||
CALL BCD_TO_STR
|
||
MOV [DATE_FMT+8], AH
|
||
MOV [DATE_FMT+9], AL
|
||
|
||
MOV AL, CL
|
||
CALL BCD_TO_STR
|
||
MOV [DATE_FMT+12], AH
|
||
MOV [DATE_FMT+13], AL
|
||
|
||
MOV AL, DH
|
||
CALL BCD_TO_STR
|
||
MOV [DATE_FMT+15], AH
|
||
MOV [DATE_FMT+16], AL
|
||
|
||
MOV AL, DL
|
||
CALL BCD_TO_STR
|
||
MOV [DATE_FMT+18], AH
|
||
MOV [DATE_FMT+19], AL
|
||
|
||
MOV AX, 0600H
|
||
MOV BH, 07H
|
||
MOV CX, 0000H
|
||
MOV DX, 184FH
|
||
INT 10H
|
||
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 10
|
||
MOV DL, 35
|
||
INT 10H
|
||
|
||
LEA DX, TITLE
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 12
|
||
MOV DL, 35
|
||
INT 10H
|
||
|
||
LEA DX, TIME_FORMAT
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV AH, 02H
|
||
MOV BH, 0
|
||
MOV DH, 14
|
||
MOV DL, 32
|
||
INT 10H
|
||
|
||
LEA DX, DATE_FMT
|
||
MOV AH, 09H
|
||
INT 21H
|
||
|
||
MOV CX, 0
|
||
MOV DX, 0
|
||
MOV AH, 86H
|
||
INT 15H
|
||
|
||
MOV AH, 01H
|
||
INT 16H
|
||
JZ MAIN_LOOP
|
||
|
||
MOV AH, 00H
|
||
INT 16H
|
||
CMP AH, 01H
|
||
JNE MAIN_LOOP
|
||
.EXIT
|
||
|
||
BCD_TO_STR PROC
|
||
PUSH DX
|
||
MOV AH, AL
|
||
AND AH, 0F0H
|
||
MOV DL, 4
|
||
SHR AH, DL
|
||
ADD AH, '0'
|
||
MOV DL, AL
|
||
AND DL, 0FH
|
||
ADD DL, '0'
|
||
MOV AL, DL
|
||
POP DX
|
||
RET
|
||
BCD_TO_STR ENDP
|
||
END
|
||
```
|
||
|
||
**说明**:INT 1AH的02H读取BCD时间,04H读取BCD日期。BCD转ASCII需要分离高低4位并加上'0'。
|
||
|
||
---
|
||
|
||
## 三、思考题
|
||
|
||
### 3.1 图形显示程序中如何切换到图形模式?
|
||
|
||
**答**:通过INT 10H的00H功能设置显示模式:
|
||
```asm
|
||
MOV AH, 00H
|
||
MOV AL, 13H ; 320x200x256色图形模式
|
||
INT 10H
|
||
```
|
||
切回文本模式:AL=03H
|
||
|
||
### 3.2 键盘计数器程序中如何检测是否有按键按下?
|
||
|
||
**答**:使用INT 16H的01H功能:
|
||
```asm
|
||
MOV AH, 01H
|
||
INT 16H
|
||
JZ NO_KEY ; ZF=1表示无按键
|
||
```
|
||
ZF=0表示有按键可用。
|
||
|
||
### 3.3 时钟显示程序中如何将二进制时间转换为ASCII字符串?
|
||
|
||
**答**:BIOS返回的是BCD码,需分离高低4位并加上ASCII'0':
|
||
```asm
|
||
MOV AH, AL
|
||
AND AH, 0F0H ; 取高位
|
||
SHR AH, 4
|
||
ADD AH, '0'
|
||
MOV DL, AL
|
||
AND DL, 0FH ; 取低位
|
||
ADD DL, '0'
|
||
```
|
||
|
||
### 3.4 上述三个程序分别使用了哪些BIOS中断?
|
||
|
||
**答**:
|
||
|
||
| 程序 | 使用的中断 |
|
||
|------|------------|
|
||
| 图形显示程序 | INT 10H (00H设置模式, 0CH画点), INT 16H (00H读取按键) |
|
||
| 键盘计数器程序 | INT 10H (02H光标, 13H显示), INT 16H (01H检查, 00H读取) |
|
||
| 时钟显示程序 | INT 10H (00H清除, 02H光标, 09H显示), INT 1AH (02H时间, 04H日期), INT 15H (86H延时), INT 16H (01H检查, 00H读取) |
|
||
|
||
---
|
||
|
||
## 四、文件清单
|
||
|
||
| 文件名 | 功能描述 |
|
||
|--------|----------|
|
||
| string_display.asm | 字符串显示程序 - 使用INT 10H的13H功能 |
|
||
| keyboard_input.asm | 键盘输入程序 - 使用INT 16H |
|
||
| read_time.asm | 读取时间程序 - 使用INT 1AH |
|
||
| sound_porgram.asm | 声音程序 - 通过端口61H/42H控制扬声器 |
|
||
| graphics_display.asm | 图形显示程序 - 图形模式13H画线 |
|
||
| keyboard_counter.asm | 键盘计数器程序 - 统计按键次数 |
|
||
| clock_display.asm | 时钟显示程序 - 实时显示系统时间 |
|
||
| REPORT.md | 本实验报告 |
|