惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

faryou的博客

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】再谈栈 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):背包DP——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):简单动规问题——程序设计思路与代码实现 【算法教程】【C/C++】递推——程序设计思路与代码实现 【算法教程】【C/C++】三分算法——程序设计思路与代码实现 【算法教程】【C/C++】二分答案——程序设计思路与代码实现 【算法教程】【C/C++】二分查找——程序设计思路与代码实现 【算法教程】【C/C++】贪心算法——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快排——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快速幂——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:进制转换——程序设计思路与代码实现 一文弄懂C++中的自定义函数 faryou的博客-2024年度总结
【汇编&硬件】时钟中断的具体实现
作者: faryou · 2026-04-11 · via faryou的博客

前言

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

代码说明

  1. 核心功能:自定义int 8h中断服务程序模拟了系统时钟中断的核心功能,包括:a.每触发一次中断,更新BIOS数据区的滴答数(自午夜起的累计中断次数,用于系统时间计算)。b.调用int 1Ch(用户定时中断钩子),允许用户扩展定时任务(如示例中每秒显示一个点)。c.发送EOI信号给8259A中断控制器,确保后续中断能被响应。d.链式调用原int 8h服务程序,保留系统默认功能(如DOS的时间管理)。
  2. 定时器配置:8253定时器通道0被配置为模式3(方波输出),计数初值为65536,对应中断频率约18.2次/秒(DOS系统默认),计算公式为:计数初值=基准频率(1193180Hz)/目标频率(18.2Hz≈65536。
  3. 中断安装与恢复:a.安装时保存原int 8h和int 1Ch的中断向量,将自定义处理程序地址写入中断向量表。b.程序退出前恢复原向量,避免破坏系统正常运行。
  4. 测试逻辑:主程序安装中断后,通过int 1Ch的自定义处理程序实现每秒显示一个点,直观展示定时中断的效果,按任意键退出并恢复系统环境。