11 KiB
实验九 BIOS中断实验报告
一、实验目的
- 掌握BIOS中断调用的基本原理和方法
- 学会使用INT 10H进行屏幕显示和图形操作
- 学会使用INT 16H进行键盘输入处理
- 学会使用INT 1AH读取系统时间和日期
- 掌握通过端口操作控制硬件的方法
二、实验内容
2.1 基础性实验
实验1-1:字符串显示程序
实验题目:使用INT 10H的13H功能显示字符串
程序源码 (string_display.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):
; 实验九 - 键盘输入程序
.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):
; 实验九 - 读取时间程序
.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):
; 实验九 - 声音程序
.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):
; 实验九 - 图形显示程序
.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):
; 实验九 - 键盘计数器程序
.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):
; 实验九 - 时钟显示程序
.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功能设置显示模式:
MOV AH, 00H
MOV AL, 13H ; 320x200x256色图形模式
INT 10H
切回文本模式:AL=03H
3.2 键盘计数器程序中如何检测是否有按键按下?
答:使用INT 16H的01H功能:
MOV AH, 01H
INT 16H
JZ NO_KEY ; ZF=1表示无按键
ZF=0表示有按键可用。
3.3 时钟显示程序中如何将二进制时间转换为ASCII字符串?
答:BIOS返回的是BCD码,需分离高低4位并加上ASCII'0':
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 | 本实验报告 |