简介这是一份面向微机原理课程学习者的实验报告聚焦8259中断控制器的中断系统与汇编中断服务程序编写。报告完整覆盖主片IRQ3、从片IRQ10和中断嵌套三个实验包含实验目的、原理说明、完整汇编源码TPC04-1.ASM等与运行效果可直接用于复习备考或实验参考。资源共1个docx文档压缩包大小4.92MB内容以文字和代码为主结构清晰便于阅读和打印。已有610人浏览学习适合高校计算机相关专业学生、准备微机原理实验报告的初学者以及需要理解可屏蔽中断处理流程的开发者。通过学习可掌握8259中断控制器初始化、中断向量设置、中断服务程序现场保护与恢复等关键技能并了解IRQ3与IRQ10的优先级差异及嵌套处理的具体实现对后续学习操作系统中断机制也有帮助。1. 中断、定时器、数码管三件事这份微机原理实验包到底在验证什么微机原理课最劝退的不是汇编语法而是寄存器、端口、中断向量这些概念在书上都能背一上实验箱就全乱套。这套实验资源把 8259 中断控制器、8253/8254 定时器、8255 并行接口和数码管四块内容串成了 11 个可直接汇编运行的 ASM 程序覆盖了微机原理实验里最常考的三大场景手动按键触发硬件中断、定时器计数与分频、多位数码管动态显示。它解决的是很具体的动手问题中断服务程序怎么写才规范、8253 初值怎么算才准、动态显示怎么做才不会闪。适合正在赶课程实验的本科生也适合想快速复习 8086 汇编与接口技术的开发者在 DOSBox 里完整复现一遍。2. 8259 中断实验主片、从片与嵌套的完整装配流程中断实验的代码看似长其实只在做四件事保存旧中断向量、装载新中断向量、修改 8259 中断屏蔽字、在中断服务程序里做处理并发送中断结束命令EOI。先把这个骨架看懂TPC04-1.ASM、TPC04-2.ASM、TPC04-3.ASM 就只是在这套骨架上换端口和向量号。2.1 先搞懂 8259 的端口与中断向量主片从片别搞混PC 机的 8259 是级联结构主片端口是 20h命令口和 21h屏蔽字口从片端口是 0A0h命令口和 0A1h屏蔽字口。实验里的 TPC04-1.ASM 用主片 IRQ3操作的是 21hTPC04-2.ASM 用从片 IRQ10操作的是 0A1h。这是最容易翻车的地方写错端口中断永远触发不了。对照几个关键数值项目主片 IRQ3从片 IRQ10中断向量号0BH72H屏蔽字端口21h0A1hIMR 中对应位bit3bit2清屏蔽用的与操作and al, 0F7hand al, 0FBh发 EOI 的目标端口20h0A0h然后再发 20hIRQ3 对应主片的第 3 号输入清零 bit3 用 0F7hIRQ10 在从片的输入排位是 IRQ8~IRQ15 里的第 2 位清零 bit2 用 0FBh。TPC04-1.ASM 挂在 0BH 上TPC04-2.ASM 挂在 72H 上这两个向量号直接决定了汇编代码里35xx、25xx中断调用的 AX 值取旧向量时mov ax, 350Bh设新向量时mov ax, 250Bh从片实验则换成 3572h 和 2572h。代码里凡是标了;!注释的地方都是主片、从片之间要改动的差异点照着替换即可。2.2 主片 IRQ3 的中断装载与退出恢复TPC04-1.ASM 逐段拆解TPC04-1.ASM 的结构是标准的“三段式”装载阶段、等待阶段、拆除阶段。核心装载代码如下mov ax,350bh ; 取 0BH 号中断的旧向量 int 21h mov intseg,es ; 段地址存入 intseg mov intoff,bx ; 偏移地址存入 intoff ; cli ; 关中断防止装载过程中被干扰 push ds mov dx,offset intproc ; DX 新 ISR 偏移地址 mov ax,seg intproc ; AX 新 ISR 段地址 mov ds,ax mov ax,250bh ; 设置 0BH 号中断向量 int 21h pop ds ; in al,21h ; 读主片 IMR mov intimr,al ; 保存原屏蔽字退出时要恢复 and al,0f7h ; 清 bit3开放 IRQ3 out 21h,al ; mov counter,0 sti ; 开中断逻辑说明先调用 DOS 功能35xx把旧中断向量取出来存进变量方便退出时恢复再用cli关中断装新向量期间不允许任何硬件中断插进来。装载新向量用的是25xx功能调用传入 DS:DX 指向新 ISR 入口。之后读回 IMR用“读-修改-写”的方式只清 IRQ3 对应的 bit3而不动其他位——如果直接写 0F7h会把别的中断源也改了。关键参数IRQ3 对应主片屏蔽字 bit3所以and al, 0F7h。0F7h 的二进制是 1111 0111只有 bit3 被清零。如果实验换成 IRQ4就得用and al, 0EFh。IMR 是“1 屏蔽、0 开放”这一点与直觉相反我当年第一次写成了or al, 08h结果越屏蔽越不触发。再看不带处理的等待循环与中断服务程序again: cmp counter,5 jb again ; cli mov al,intimr out 21h,al ; 恢复原 IMR mov dx,intoff mov ax,intseg mov ds,ax mov ax,250bh int 21h ; 恢复旧中断向量 sti .exit 0 intproc proc sti ; 开中断允许更高优先级中断打断 push ax push si push ds mov ax,data mov ds,ax ; 重设 DS因为中断可能发生在任意代码位置 inc counter ; 中断计数加 1 mov si,offset msg call dpstri ; 显示 TPCA interrupt No.3! mov al,20h out 20h,al ; 发送 EOI 给主片 8259 pop ds pop si pop ax iret intproc endp逻辑说明主程序在sti之后进入一个死等循环靠 ISR 里递增counter来跳出。跳出后先关中断把之前保存的 IMR 写回 8259再恢复旧中断向量。这个拆除流程非常关键不恢复的话程序退出后系统里的其他程序再调用 0BH 号中断就会跳到一段已经不存在的代码上直接死机。ISR 里的要点入口必须重新加载 DS 到data因为中断发生时 CPU 可能在任一段代码里DS 不一定指向数据段末尾必须向 20h 端口发送 20h 值作为 EOI否则 8259 认为中断服务还没结束后续同一级及更低级的中断全部被锁死。中断嵌套实验在此基础上还要在 ISR 开头加sti让 CPU 在服务过程中重新打开中断允许标志。2.3 中断嵌套为什么“看不到”优先级、IF 标志和延时窗口理论上 IRQ10 优先级高于 IRQ3主片 IRQ0~IRQ7 优先级从高到低是 IRQ0 最高但从片整体接在主片 IRQ2 上从片内部的 IRQ8~IRQ15 优先级又高于主片其余输入所以 IRQ10 可以打断 IRQ3。但 TPC04-3.ASM 在真机上跑如果只按一次键屏幕上通常看到的是两条完整消息先后出现没有“穿插”效果。原因很简单两个 ISR 执行时间都太短从显示到返回只有几十微秒按键又有先后时差根本没有机会互相打断。TPC04-3.ASM 的解法是在 ISR 里加延时窗口。地址为intproc的 IRQ3 服务程序流程是显示 “No.3!”调用delay延时再显示 “No.3 again!”。delay用的是双重循环delay proc push bx push cx mov bx,2000 delay1: mov cx,0 delay2: loop delay2 dec bx jne delay1 pop cx pop bx ret delay endp逻辑说明内层loop delay2在 CX0 时循环 65536 次外层 bx 控制 2000 轮总延时时长约几百毫秒。这个窗口就是留给 IRQ10 打断的“空档”。操作时先按 IRQ3 的单脉冲键看到屏幕出现 “No.3!” 后趁第二条 “No.3 again!” 还没显示完立刻按 IRQ10 的键。如果时序对准屏幕上会出现这种输出TPCA interrupt No.3! TPCA interrupt No.10! TPCA interrupt No.10 again! TPCA interrupt No.3 again!这说明 IRQ10 的服务程序在 IRQ3 服务程序延时期间插入执行嵌套成立。如果始终看不到穿插先把delay里的mov bx,2000改成mov bx,20000把窗口拉长十倍再试。窗口太长也有副作用——ISR 阻塞时间过久同一个中断源再次触发时会丢失请求所以调试时放大、验证完了再改回来。3. 8253/8254 定时器实验方式 0、方式 3 与级联分频的初值怎么算8253 这一章的核心不是背控制字而是搞懂两件事写进去的初值决定什么、读出来的计数值代表什么。TPC 系列三个程序恰好覆盖方式0计数、方式3方波、定时中断三个典型用法。3.1 端口地址与控制字通道、读写格式、方式三位字段怎么拼实验板上 8253 的端口分配是固定的计数器0 地址 280h、计数器1 地址 281h、计数器2 地址 282h、控制字寄存器 283h。控制字格式是SC1、SC0通道选择、RL1、RL0读写格式、M2、M1、M0工作方式、BCD计数进制。以 TPC05-1.ASM 的方式0为例mov al,10h ; 0001 0000 mov dx,283h out dx,al ; 写控制字通道0、只读写低字节、方式0、二进制逻辑说明10h 拆开是 SC1SC000选中通道0RL1RL001表示只读/写低字节后续送初值时只需输出一个字节M2M1M0000方式0BCD位0用二进制计数。方式0的特点是写入初值后输出变为低电平每来一个计数脉冲就减 1减到 0 时输出变高。这个“计数减到 0 输出跳变”的行为就是后面用逻辑笔观察 OUT0 电平变化的依据。初值参数要注意方式0 的计数初值可以是一个字节最多 255也可以是两个字节。TPC05-1 里初值取 5在 1~9 之间便于屏幕显示一位数。写入方式是mov al,5然后out dx,al直接送低字节这对应控制字里 RL01。如果用 16 位初值就得像方式3程序那样先写低字节再写高字节。3.2 TPC05-1 与 TPC05-2脉冲计数读回的“去重”技巧与级联方波方式0 的读回有个坑8253 在计数过程中直接读计数值读到的可能是当前正在变化的计数值不稳定。TPC05-1.ASM 用了一个朴素办法来避开这个问题mov al,5 ; 计数初值为 5 out dx,al mov ah,al ; ah 保存上一次读到的值 again: call wait ; 等待约 1ms in al,dx ; 读当前计数值 cmp al,ah jz again ; 与上次相同则不显示 push ax call dispuib ; 显示当前计数值 call dispcrlf pop ax mov ah,al ; 更新“上一次的值” cmp al,0 jnz again .exit 0逻辑说明程序先把初值 5 写入计数器进入循环后每隔一小段时间读取一次计数值。由于 8253 是减计数读回来的值会从 4 依次减到 0。cmp al,ah是比较当前值与上一次读到的值相同就跳过显示。这个“去重”逻辑解决的正是计数变化过程中读到重复值或半稳定值的问题——虽然不能替代硬件锁存但在实验场景下足够让显示看起来是连续递减的。常见做法是改用 8253 的锁存命令向控制字端口写 00h锁存通道0此时计数器内部计数值被冻结到锁存寄存器再读 280h 就能拿到稳定值。锁存命令不影响计数继续比“读两次比较”更干净。TPC05-2.ASM 的级联方波则是标准的分频用法mov dx,283h mov al,36h ; 0011 0110 out dx,al ; 通道0方式3、双字节读写、二进制 mov ax,1000 mov dx,280h out dx,al ; 先写低字节 mov al,ah out dx,al ; 再写高字节 ; mov dx,283h mov al,76h ; 0111 0110 out dx,al ; 通道1方式3、双字节读写、二进制 mov ax,1000 mov dx,281h out dx,al mov al,ah out dx,al逻辑说明36h 拆开是通道0、RL11 双字节、M011 方式3、二进制76h 同理对应通道1。通道0 的 CLK0 接实验板 1MHz 时钟初值 1000输出 OUT0 就是 1MHz ÷ 1000 1kHz 方波。这个 1kHz 信号又作为通道1 的 CLK1 输入通道1 初值 1000输出 OUT1 就是 1kHz ÷ 1000 1Hz 方波。用逻辑笔或 LED 可以看到 OUT1 每 1 秒翻转一次电平。这里要注意级联的参数关系总输出频率 输入时钟 ÷ (初值1 × 初值2)。想要 1Hz可以拆成 1000×1000也可以拆成 2000×500只要乘积等于分频系数就行。初值两个字节时可以覆盖 0~65535写入顺序必须是先低字节后高字节顺序写反8253 会按照高字节写入低字节、低字节写入高字节的错误顺序拼出初值输出频率完全不对。我在复现时踩过这个坑现象是输出频率比预期大了 256 倍查了半天才发现是写反了。3.3 定时 1 秒中断TPC05-3.ASM 里 8253 与 8259 的联动TPC05-3.ASM 把前面两个实验串起来了8253 通道0、通道1 都设成方式3级联后 OUT1 输出 1Hz 方波这个方波信号通过实验板的电路接到主片 IRQ3 上变成每秒一次的中断请求。8253 负责“定时”8259 负责“分发”程序逻辑与中断实验类似只是中断来源从手动按键变成了定时器脉冲。中断服务程序里做的事情就是计数显示intproc proc sti push ax push si push ds mov ax,data mov ds,ax inc byte ptr counter mov si,offset msg call dpstri ; 显示 one second passed ! mov al,20h out 20h,al ; EOI pop ds pop si pop ax iret intproc endp参数要点由于输出是 1Hz 方波IRQ3 每个上升沿触发一次所以 counter 每秒加 1主程序等待 counter 等于 5 后退出整个程序运行 5 秒。如果把 8253 初值从 1000 改成 500方波频率变成 2Hz程序运行时间就缩短到 2.5 秒。改初值前先算清楚分频系数CLK 是 1MHz目标频率是 F则初值 1_000_000 ÷ F。级联时把初值拆成两个因子的乘积即可。4. 8255 驱动数码管段码表、动态扫描与时钟显示的时序数码管实验表面上是显示数字实际上考的是并行接口 8255 的端口配置和多位数码管的时分复用。TPC08-1 到 TPC08-5 五个程序难度递增最后一个是把 8253 定时中断和 8255 显示合在一起做时钟属于综合题。4.1 共阴极段码表为什么 3Fh 是 0、06h 是 1实验台上的数码管是共阴极公共端接地各段加高电平点亮。段码按 a、b、c、d、e、f、g、dp 的顺序排列成 8 位数据DP 在最低位接段码的 bit0。来一个关键参数表这套段码在 TPC08 系列程序里反复使用显示数字段码十六进制点亮段03Fha b c d e f106hb c25Bha b d e g34Fha b c d g466hf g b c56Dha f g c d67Dha f e d c g707ha b c87Fh全部点亮96Fha b c d f g表格里的段码顺序是 D7~D0 对应 dp g f e d c b a。比如数字 0a~f 都点亮dp 和 g 灭二进制是 0111 1111即 3Fh。数字 1 只点亮 b、c 两段值是 0000 0110即 06h。写段码表时最容易错的是把 6 和 9 的位置搞混6D h 与 6Fh 只差一位查表时对照点亮段确认一遍再烧录。8255 的端口映射在实验板上是固定的A口 288h、B口 289h、C口 28Ah、控制口 28Bh。TPC08-1.ASM 里把 A口 设为输出方式0mov dx,28bh mov ax,80h ; 1000 0000 out dx,al80h 控制字表示A口方式0输出、B口方式0输出、C口输出。这个程序只做一位静态显示PA0~PA7 接到数码管段码位码 S3 接 5V 选通键盘输入一个 0~9 的数字查段码表后从 A口 输出即可点亮对应数字。4.2 动态显示时序先段码、再位选、切换前必须消隐4 位数码管共用 8 根段码线不能同时点亮四个不同的数字只能靠快速轮流扫描“骗”过眼睛。TPC08-2.ASM 显示固定数字 3456核心循环是scan_loop: mov si,offset table ; 段码表首地址 mov bl,0feh ; 位选初值PB00 表示选中 S0? 需按实际接法 ... next_digit: mov al,[si] ; 取出当前数字的段码 mov dx,288h out dx,al ; 段码送到 A口先亮段 mov al,bl mov dx,289h out dx,al ; 位选送到 B口选中某一位 call delay ; 延时约 1ms保持点亮 mov al,0 mov dx,288h out dx,al ; 段码清零消隐 inc si ; 指向下一位数字的段码 rol bl,1 ; 位选移动一位 ...逻辑说明每次循环只点亮一位。先送段码再送位选是为了避免位选切换瞬间把上一数字的段码残留在新选中的这一位上造成“重影”。点亮一位后延时 1~2ms然后在切换下一位之前把段码口清零这一句就是消隐不能省。四位数轮流扫一遍约 4ms刷新率 250Hz人眼看到的就是稳定不闪的 3456。延时长短需要现场调太短数码管亮度不够太长能明显看到位与位之间的切换闪烁。我习惯把这句延时控制在 1ms 量级四位数刷新率刚好过 200Hz亮度也够。另外位选信号如 B口 送的是反相驱动实验中位码输入端高电平选中实际送值要根据实验板接线调整最常见的错误是位选电平高低写反结果是数码管全灭或全亮。4.3 时钟显示 TPC08-5中断改数据、主循环刷显示TPC08-5 是把实验B和实验C结合起来的综合程序8253 定时 1 秒产生中断中断服务程序累加秒和分钟主程序不断把当前时间拆成四个数字查段码表送到数码管显示。ISR 里的时间逻辑inc second cmp second,60 jb no_carry ; 秒不到 60 则跳过进位 mov second,0 inc minute cmp minute,60 jb no_carry mov minute,0 no_carry:逻辑说明second 从 0 数到 59到 60 时清零并给 minute 加 1minute 同样到 60 清零。因为初值全部是二进制这里直接比较十进制常量 60 用的是二进制比较second 是 byte0~59 内二进制的值正好与十进制一致所以这种写法成立。拆位时用 div 10 分别取十位和个位商是十位段码索引余数是个位段码索引。架构上有一个值得保留的习惯ISR 里只改内存变量不在 ISR 里直接驱动数码管。数码管刷新由主循环持续扫描完成。中断服务程序尽量短把耗时操作放到主循环是嵌入式开发里通用的原则也适合这套实验环境——8259 在中断响应期间是串行工作的ISR 拖得越长其他中断被阻塞的时间越久。显示顺序上实验要求前两位数码管显示分钟、后两位显示秒。分钟和秒各自拆出十位、个位按“分钟十位、分钟个位、秒十位、秒个位”的顺序依次查表送显配合位选扫描就是一个可用的 4 位时钟。想要把 1 小时进位也做进去就在 minute 到 60 时清零并给 hour 加 1同样判断到 24 再清零逻辑完全对称。5. 避坑记录五个实测中的翻车点与排查路径这套实验资源里最容易卡住人的不是汇编语法而是中断和定时器的“硬件时序”问题。以下五个坑是我在实际复现过程中踩过的按现象、原因、解决的顺序列出来遇到同类问题可以直接对着查。现象1按一次单脉冲开关屏幕显示正常之后再按任何键都没反应。原因中断服务程序末尾忘了发 EOI8259 内部的中断服务寄存器还处于“正在服务中”状态相同优先级和更低优先级的中断请求全部被压住。解决在 ISR 返回指令iret之前补上mov al,20h和out 20h,al。从片中断 IRQ10 的服务程序还要先向 0A0h 端口发 EOI再向 20h 发 EOI顺序不能反先清从片再清主片。检查代码时优先看out 20h,al这一句在不在iret之前。现象2程序运行完退出后再运行其他程序一按键就死机或屏幕乱码。原因退出前没有恢复旧中断向量和 IMR。程序把 0BH 号向量改成了自己的 ISR退出后向量还指向已结束的代码段其他程序触发 0BH 中断就跳到无效地址。IMR 没恢复同理可能导致某些中断源被永久屏蔽。解决退出时按“关中断 → 恢复 IMR → 恢复向量 → 开中断”的顺序拆。TPC04-1.ASM 末尾那段cli、写回intimr、把intseg:intoff通过25xx功能写回、再sti每一句都不能删。这是标准拆除流程不是可有可无的收尾。现象3TPC05-1 显示的计数值不是递减的 4、3、2、1、0而是偶尔重复或跳变。原因8253 在计数过程中直接读端口读到的计数值可能处于字节更新瞬间低字节不稳定。代码里cmp al,ah是软件去重但仍不能保证读到的是某一瞬间的准确值。解决换用 8253 的锁存命令。向控制字端口写 00h 把计数器0 当前值锁存到寄存器然后再读 280h。锁存期间计数仍在继续不影响后续测量。如果不想改代码就接受“偶尔重复显示一次”的现象实验结论不受影响。现象44 位数码管显示 3456数字内容对但看起来发花前一位的残影叠在后一位上。原因切换位选之前没有消隐。当前一位的段码还在 A口 上时位选已经切到下一位上一位的段码就在新位选上亮了一下形成拖影。解决在改位选寄存器之前先把 A口 输出清零这个动作必须在段码数据更新之后、位选切换之前执行。扫描延时控制在 1~2ms不要超过 5ms。如果显示还闪优先检查延时而不是代码逻辑。现象5中断嵌套实验无论先按哪个键、按多快输出都是两条消息完全分开没有穿插。原因ISR 执行时间太短IRQ3 的 ISR 从显示到返回只有几十微秒手动按键间隔远大于这个窗口IRQ10 根本没有机会在 IRQ3 服务期间触发。另外 ISR 开头如果没有stiCPU 在中断服务期间一直处于关中断状态高优先级中断也无法打断。解决把delay里的外层循环次数调大比如mov bx,20000让 IRQ3 的服务窗口拉到几百毫秒。操作时先按 IRQ3看到屏幕出现第一条 “No.3!” 就立刻按 IRQ10嵌套现象就能稳定复现。ISR 开头必须有sti指令这是嵌套的前提条件。6. 把中断嵌套做成可观测给 ISR 加一个特征字节数组嵌套实验最让人头疼的是“全靠肉眼盯屏幕判断顺序”。屏幕刷新有延迟两条消息交错时很难确认谁先谁后。我的做法是在每个 ISR 入口写一个特征字节到内存数组等主程序退出后把这段序列打印出来执行顺序一目了然。思路是在数据段定义一个序列缓冲区seqbuf byte 32 dup(0) ; 记录中断进入顺序 seqidx byte 0 ; 当前写入位置在 IRQ3 的 ISR 入口写 33h在 IRQ10 的 ISR 入口写 0AAhintproc proc sti push ax push si push ds mov ax,data mov ds,ax mov si,offset seqidx mov al,[si] ; 当前写入位置 inc byte ptr [si] ; 写完位置后移 mov si,offset seqbuf xor ah,ah add si,ax ; SI 指向当前写入位置 mov byte ptr [si],33h ; IRQ3 的标记 ... intproc endp主程序退出前循环打印seqbuf里的值如果输出是33 33 33 33 33说明根本没有嵌套如果出现33 AA AA 33这样的序列说明 IRQ10 确实插进了 IRQ3 的服务窗口。用这种方法嵌套实验从“按运气看屏幕”变成了可重复验证的操作配合把delay的 bx 调大几乎每次都能按出嵌套。环境上提一句DOSBox 能编译运行这套汇编代码用masm TPC04-1.asm加link TPC04-1.obj就能出可执行文件。但 DOSBox 对硬件中断的模拟是周期性的手动单脉冲按键这类外部触发无法在虚拟机里模拟所以 DOSBox 适合验证程序逻辑和编译链接流程想真正看到中断嵌套效果还是得有实验板或配套硬件。这也是这套资料里代码能跑通但现象“玄学”的根本原因——中断实验一半是软件一半是硬件时序。从那次以后我每次做中断实验都强制自己先加特征字节记录再跑把“猜现象”变成“读数据”。这套实验包里 11 个 ASM 源码和报告正好覆盖了中断、定时器、数码管三块硬骨头按章对照改参数、加延时、看输出完整跑一遍微机原理的接口实验算是真正落地了。希望帮到你。本文还有配套的精品资源点击获取