
























int 8h是8086系统中由8253定时器通道0触发的系统时钟中断,主要用于维持系统时间、触发定时任务等,默认由BIOS或DOS内核实现。以下是一个模拟int 8h核心功能的自定义中断服务程序,包含系统时间更新、定时中断处理等功能。
; 常量定义
TIMER_CTRL_PORT equ 43h ; 8253定时器控制端口
TIMER_CH0_PORT equ 40h ; 定时器通道0端口
BASE_FREQ equ 1193180 ; 定时器基准频率(Hz)
CLK_TICKS_PER_SEC equ 18 ; 每秒时钟滴答数(DOS默认,18.2次/秒)
BIOS_TIME_SEG equ 0040h ; BIOS时间存储段地址
BIOS_TIME_OFF equ 006Ch ; BIOS时间存储偏移(dword:自午夜起的滴答数)
code segment
assume cs:code, ds:data
; 自定义int 8h中断服务程序
; 功能:
; 1. 定时器中断处理(维持系统时钟)
; 2. 更新BIOS时间(滴答数累计)
; 3. 调用原int 8h服务程序(链式调用,保留系统功能)
int8_proc proc far
push ax
push bx
push cx
push dx
push si
push di
push es
push ds ; 保存所有寄存器
; 步骤1:更新BIOS系统时间(滴答数)
mov ax, BIOS_TIME_SEG
mov es, ax ; ES指向BIOS数据段
inc dword ptr es:[BIOS_TIME_OFF] ; 滴答数+1(每中断一次加1)
; 步骤2:触发int 1Ch(用户定时中断,默认无操作,可由用户扩展)
int 1Ch ; 调用用户定时中断钩子
; 步骤3:发送EOI信号给8259A中断控制器,允许后续中断
mov al, 20h ; EOI命令
out 20h, al ; 发送给主8259A
; 步骤4:链式调用原int 8h服务程序(保留系统默认功能)
call dword ptr cs:[orig_int8] ; 调用原int 8h
; 恢复寄存器并返回
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret ; 中断返回
int8_proc endp
; 初始化定时器通道0(设置中断频率)
; 频率 = BASE_FREQ / 计数初值 → 计数初值 = BASE_FREQ / 目标频率
init_timer proc
; 计算计数初值(18.2Hz对应的初值:1193180 / 18.2 ≈ 65536)
mov ax, 0 ; 计数初值=65536(0000h,16位最大值)
; 配置定时器通道0:模式3(方波输出),16位计数
mov al, 00110110b ; 控制字:通道0,读写高8+低8,模式3,二进制
out TIMER_CTRL_PORT, al
; 写入计数初值(65536的低8位和高8位均为00h)
mov al, 0
out TIMER_CH0_PORT, al ; 低8位
out TIMER_CH0_PORT, al ; 高8位
ret
init_timer endp
; 安装自定义int 8h中断(替换系统默认中断)
install_int8 proc
cli ; 关中断,防止安装过程被打断
mov ax, 0
mov ds, ax ; DS指向中断向量表(0段)
; 保存原int 8h中断向量(段:偏移)
mov ax, ds:[8*4] ; 原偏移
mov word ptr cs:[orig_int8], ax
mov ax, ds:[8*4 + 2] ; 原段
mov word ptr cs:[orig_int8 + 2], ax
; 写入自定义中断服务程序地址到int 8h向量
mov ax, offset int8_proc
mov ds:[8*4], ax ; 偏移
mov ax, cs
mov ds:[8*4 + 2], ax ; 段
sti ; 开中断
ret
install_int8 end
; 恢复原int 8h中断向量(程序退出时调用)
restore_int8 proc
cli
mov ax, 0
mov ds, ax
; 恢复原向量
mov ax, word ptr cs:[orig_int8]
mov ds:[8*4], ax
mov ax, word ptr cs:[orig_int8 + 2]
mov ds:[8*4 + 2], ax
sti
ret
restore_int8 endp
; 测试用的int 1Ch用户定时中断(每秒显示一次)
int1c_proc proc far
push ax
push bx
push cx
push dx
push ds
mov ax, data
mov ds, ax ; 初始化数据段
; 每CLK_TICKS_PER_SEC次中断(约1秒)执行一次
inc word ptr [tick_count]
mov ax, [tick_count]
cmp ax, CLK_TICKS_PER_SEC
jne int1c_end
; 1秒到,显示字符'.'
mov ah, 02h
mov dl, '.'
int 21h
mov word ptr [tick_count], 0 ; 重置计数器
int1c_end:
pop ds
pop dx
pop cx
pop bx
pop ax
iret
int1c_proc endp
; 安装int 1Ch用户定时中断
install_int1c proc
cli
mov ax, 0
mov ds, ax
; 保存原int 1Ch向量
mov ax, ds:[1Ch*4]
mov word ptr cs:[orig_int1c], ax
mov ax, ds:[1Ch*4 + 2]
mov word ptr cs:[orig_int1c + 2], ax
; 写入自定义int 1Ch处理程序
mov ax, offset int1c_proc
mov ds:[1Ch*4], ax
mov ax, cs
mov ds:[1Ch*4 + 2], ax
sti
ret
install_int1c endp
; 恢复原int 1Ch中断
restore_int1c proc
cli
mov ax, 0
mov ds, ax
mov ax, word ptr cs:[orig_int1c]
mov ds:[1Ch*4], ax
mov ax, word ptr cs:[orig_int1c + 2]
mov ds:[1Ch*4 + 2], ax
sti
ret
restore_int1c proc
; 主程序:安装中断并测试
main:
mov ax, data
mov ds, ax ; 初始化数据段
; 安装int 8h和int 1Ch中断
call install_int8
call install_int1c
call init_timer ; 初始化定时器
; 等待用户按键退出
mov ah, 01h
int 21h ; 等待按键
; 恢复系统中断
call restore_int1c
call restore_int8
; 程序退出
mov ah, 4Ch
int 21h
; 数据区(在代码段中定义,避免额外段操作)
orig_int8 dd 0 ; 原int 8h中断向量(段:偏移)
orig_int1c dd 0 ; 原int 1Ch中断向量
tick_count dw 0 ; 用于int 1Ch的滴答计数器
code ends
data segment
data ends ; 数据段仅作占位
end main此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。