8088 单板机 汇编 NMI 中断程序示例 (脱离 DOS 环境)

article/2025/7/28 2:53:56
; =================================================================
; nmi_demo.asm - 8088 单板机 NMI 中断演示程序
; 脱离 DOS 环境,直接运行在裸机上
; =================================================================; 硬件配置假设:
; - 8088 CPU @ 4.77MHz
; - 8259 PIC (可编程中断控制器)
; - 8255 PPI (可编程外设接口) 连接 LED
; - 7 段数码管显示
; - NMI 按钮连接到 NMI 引脚PORT_PPI_A     EQU 60h    ; 8255 PPI 端口 A (LED 控制)
PORT_PPI_B     EQU 61h    ; 8255 PPI 端口 B (7 段数码管数据)
PORT_PPI_C     EQU 62h    ; 8255 PPI 端口 C (数码管位选)
PORT_PPI_CTRL  EQU 63h    ; 8255 PPI 控制端口PORT_PIC_CMD   EQU 20h    ; 8259 PIC 命令端口
PORT_PIC_DATA  EQU 21h    ; 8259 PIC 数据端口; 7 段数码管编码 (共阴极)
;       0     1     2     3     4     5     6     7     8     9
SEG7 db 3Fh, 06h, 5Bh, 4Fh, 66h, 6Dh, 7Dh, 07h, 7Fh, 6Fhorg 0FFF0h                ; 8088 复位向量地址
reset:jmp 0F000h:start      ; 跳转到实际起始地址org 0F000h                ; BIOS 区域起始地址 (典型); === 主程序入口 ===
start:; 设置段寄存器cli                   ; 禁用中断mov ax, csmov ds, ax            ; DS = CSmov ss, ax            ; SS = CSmov sp, 0FFFEh        ; 栈指针在 64KB 顶部; 初始化硬件call init_ppi         ; 初始化 8255 PPIcall init_pic         ; 初始化 8259 PICcall init_nmi         ; 初始化 NMI 处理; 显示启动信息call clear_displaymov si, msg_welcomecall display_string; 主循环 - 等待 NMIsti                   ; 启用中断
main_loop:hlt                   ; 暂停 CPU 等待中断jmp main_loop; === 初始化 8255 PPI ===
init_ppi:; 设置 8255 控制字: 端口A输出, 端口B输出, 端口C输出, 模式0mov al, 10000000b     ; 控制字: 1 (I/O模式) 00 (A组模式0) 0 (A输出) 1 (C上输出) 0 (B组模式0) 0 (B输出) 0 (C下输出)out PORT_PPI_CTRL, al; 初始状态: 关闭所有 LED 和数码管xor al, alout PORT_PPI_A, al    ; 关闭 LEDout PORT_PPI_B, al    ; 关闭数码管段out PORT_PPI_C, al    ; 关闭数码管位选ret; === 初始化 8259 PIC ===
init_pic:; ICW1: 边沿触发, 级联, 需要 ICW4mov al, 00010011b     ; ICW1: 1 (需要ICW4) 0 (级联) 0 (边沿触发) 1 (需要ICW4) 1 (主PIC)out PORT_PIC_CMD, al; ICW2: 中断向量基地址mov al, 08h           ; 中断向量号从 08h 开始out PORT_PIC_DATA, al; ICW3: 主片 IR2 连接从片 (本示例不使用从片)mov al, 00000100b     ; IR2 连接从片 (00000100b)out PORT_PIC_DATA, al; ICW4: 8086/88 模式mov al, 00000001b     ; ICW4: 0 (非特殊全嵌套) 0 (非缓冲) 0 (主片) 1 (8086模式)out PORT_PIC_DATA, al; OCW1: 屏蔽所有中断 (NMI 不受影响)mov al, 11111111b     ; 屏蔽所有 IRQout PORT_PIC_DATA, alret; === 初始化 NMI 处理 ===
init_nmi:; 保存原始 NMI 向量xor ax, axmov es, ax            ; ES = 0000h (中断向量表段)mov di, 2*4           ; NMI 向量位置 (中断号 2 * 4 字节)mov ax, [es:di]       ; 获取偏移mov [old_nmi_offset], axmov ax, [es:di+2]     ; 获取段地址mov [old_nmi_segment], ax; 设置新的 NMI 处理程序climov word [es:di], nmi_handler    ; 设置新偏移mov [es:di+2], cs                ; 设置段地址 (当前代码段)sti; 启用 NMI (清除 CMOS 寄存器第7位)in al, 70hand al, 01111111b     ; 清除第7位 (NMI 启用)out 70h, alret; === NMI 中断处理程序 ===
nmi_handler:; 保存寄存器push axpush bxpush cxpush dxpush sipush ds; 设置数据段mov ax, csmov ds, ax; 增加 NMI 计数器inc byte [nmi_count]; 在 LED 上显示 NMI 发生mov al, 0FFh          ; 点亮所有 LEDout PORT_PPI_A, al; 在数码管上显示计数call update_display; 延迟一段时间 (视觉反馈)mov cx, 0FFFFh
delay_loop:noploop delay_loop; 关闭 LEDxor al, alout PORT_PPI_A, al; 发送中断结束信号 (EOI)mov al, 20h           ; 非特定 EOIout PORT_PIC_CMD, al; 恢复寄存器pop dspop sipop dxpop cxpop bxpop axiret                  ; 中断返回; === 更新数码管显示 ===
update_display:; 显示 NMI 计数mov al, [nmi_count]and al, 0Fh           ; 只显示低4位; 获取数码管编码mov bx, SEG7xlat                  ; AL = DS:[BX + AL]; 输出到数码管out PORT_PPI_B, al    ; 段数据; 启用第一个数码管mov al, 00000001b     ; 位选: 启用第一个数码管out PORT_PPI_C, alret; === 清除数码管显示 ===
clear_display:xor al, alout PORT_PPI_B, al    ; 关闭所有段out PORT_PPI_C, al    ; 关闭所有位选ret; === 显示字符串 (SI = 字符串地址) ===
display_string:push axpush bxpush cxpush dxpush simov cx, 0             ; 字符计数器
next_char:lodsb                 ; 加载下一个字符test al, al           ; 检查是否结束jz display_done; 查找字符的7段编码mov bx, SEG7xlat                  ; AL = 7段编码; 输出到数码管out PORT_PPI_B, al    ; 段数据; 设置位选mov al, clinc alout PORT_PPI_C, al    ; 位选; 延迟push cxmov cx, 1000h
delay_char:loop delay_charpop cxinc cx                ; 下一个数码管cmp cx, 4             ; 最多4个数码管jb next_chardisplay_done:pop sipop dxpop cxpop bxpop axret; === 数据区 ===
msg_welcome db 'NMI', 0   ; 欢迎消息 (以0结尾); NMI 计数器
nmi_count db 0; 原始 NMI 向量保存位置
old_nmi_offset  dw 0
old_nmi_segment dw 0; === 填充到 64KB ROM 结束 ===
times 0FFFFh - $ + 1 db 0FFh


http://www.hkcw.cn/article/ORDaEATmlG.shtml

相关文章

HRMS数据模型:解密组织的数字基因库与智能管理引擎

摘要 随着数字化转型浪潮席卷全球,人力资源管理系统(HRMS)正升级为企业的“数字基因库”,承载着组织、岗位与人员的动态管理使命。本文基于创新的“三维动态耦合模型”,系统剖析HRMS数据模型设计理念、关键组件与业务…

Nature|张泽民团队提出CM模型新视角 | 单细胞如何走向系统生态?|细胞模块概念新研究范式

端午节儿童节,假期到了,不知道大家有没有安排出游,去哪里放松、吃到什么特别的美食?长大之后,儿童节就悄悄地从我们的生活中“毕业”了,忙碌中偶尔的童心和好奇,还是要有的。 今天分享最近学习…

题单:最大公约数(辗转相除法)

题目描述 所谓 “最大公约数(GCD)” ,是指所有公约数中最大的那个,例如 12 和 1818 的公约数有 1,2,3,6 ,所以 12 和 18 的最大公约数为 6 。 辗转相除法,又名欧几里德算法(Euclidean Algorit…

75岁薛家燕谈小17岁男友 甜蜜恋情持续12年

近日,75岁的资深艺人薛家燕在接受采访时谈及与小17岁男友Andy的恋情,难掩甜蜜。她表示男友多年来对她一直很好。两人通过朋友介绍相识,最初通过电子邮件交流。薛家燕曾因年龄差距犹豫退缩,担心对方只是一时喜欢,甚至一度提出分手。但Andy以真诚打动了她,两人相恋12年,尽…

女子骑电动三轮闯卡强行上高速 收费站工作人员尽力拦截未果

5月31日,有网友在抖音平台发布了一段行车记录仪视频。视频显示,在陕西省渭南市华州收费站,一名女子骑着电动三轮车强行闯卡驶上了高速公路。根据视频内容,当天下午6点45分左右,这名女子骑着电动三轮车紧跟在一辆汽车后面。收费站工作人员发现后,试图让她退回去,但她并未…

新规施行拒绝刷脸有依据了 保护个人信息安全

近年来,刷脸技术在识别个人信息方面的应用日益广泛,从小区门禁、酒店登记到交通出行和金融支付,在经济社会的各个领域几乎都能见到“刷脸”技术的应用。然而,这种便捷性背后也隐藏着不容忽视的风险。为规范人脸识别技术的使用并保护个人信息安全,国家互联网信息办公室和公…

河南水库水位下降现千佛石窟 佛像多有残损引发关注

近日,河南省鹤壁市淇县夺丰水库水位下降后,一处千佛石窟显露出来,引发网友关注。该石窟洞壁布满佛像,但不少佛头和手臂几乎都消失不见。淇县县委宣传部一负责人表示,这处石窟当地人一直都知道,民间称其为天竺石窟或千佛洞。该负责人曾在十多年前两次进入石窟参观。夺丰水…

郑钦文回应晋级:再打两盘都没问题 体力充沛信心足

郑钦文鏖战3盘,耗时2小时47分钟,以2-1击败萨姆索诺娃,晋级法网女单8强,刷新了个人在法网的最佳战绩。赛后接受采访时,她表示自己还有很多能量,甚至开玩笑说如果女子比赛有五盘制,她再打两盘也没问题。这场比赛非常激烈,对手发挥出色,给郑钦文施加了很大压力,她在底线…

当地称瘦弱骆驼主人此前已养死一只 另一只现状堪忧

近日,多名网友在社交平台上发帖称,在福建省福州市平潭县流水镇路边发现一只疑似被遗弃的骆驼。这只骆驼体型瘦弱,趴伏在地上,毛发稀疏,周围没有任何遮蔽,引起了广泛关注。6月1日,一名当地居民表示,5月9日她曾路过该路段,看到有两只骆驼趴在路边;今天早上再去查看时,…

现场球迷合唱《日不落》送给郑钦文 法网晋级喜迎海鲜大餐

5月31日,中国选手郑钦文在2025年法国网球公开赛32强战中表现出色,以6-3、6-4直落两盘击败18岁的加拿大资格赛黑马姆博科,挺进16强,追平个人纪录。比赛结束后,她在巴黎街头漫步并享受了一顿海鲜大餐。首盘比赛中,郑钦文发球状态极佳,一发得分率达78%,轰出3记ACE球,并通…

12.springCloud AlibabaSentinel实现熔断与限流

目录 一、Sentinel简介 1.官网 2.Sentinel 是什么 3.Sentinel 的历史 4.Sentinel 基本概念 资源 规则 5.Sentinel 功能和设计理念 (1).流量控制 什么是流量控制 流量控制设计理念 (2).断降级 什么是熔断降级 熔断降级设计理念 (3).系统自适应保护 6.主要工作机制…

【GPT入门】第40课 vllm与ollama特性对比,与模型部署

【GPT入门】第40课 vllm与ollama特性对比,与模型部署 1.两种部署1.1 vllm与ollama特性对比2. vllm部署2.1 服务器准备2.1 下载模型2.2 提供模型服务 1.两种部署 1.1 vllm与ollama特性对比 2. vllm部署 2.1 服务器准备 在autodl 等大模型服务器提供商,…

PTA-根据已有类Worker,使用LinkedList编写一个WorkerList类,实现计算所有工人总工资的功能。

目录 1.问题描述 2.函数接口定义: 3.裁判测试程序样例: 4.输入和输出样例 输入样例: 输出样例: 5.实现代码 1.问题描述 Main类:在main方法中,调用constructWorkerList方法构建一个Worker对象链表…

Maven概述,搭建,使用

一.Maven概述 Maven是Apache软件基金会的一个开源项目,是一个有优秀的项目构建(创建)工具,它用来帮助开发者管理项目中的jar,以及jar之间的依赖关系,完成项目的编译,测试,打包和发布等工作. 我在当前学习阶段遇到过的jar文件: MySQL官方提供的JDBC驱动文件,通常命名为mysql-…

基于Canvas实现抽奖转盘

本案例基于画布组件、显式动画,实现的一个自定义抽奖圆形转盘。包含如下功能: 通过画布组件Canvas,画出抽奖圆形转盘。通过显式动画启动抽奖功能。通过自定义弹窗弹出抽中的奖品。 一、案例效果截图 案例运行效果如图11-28所示。 图11-27 …

【 SpringCloud | 微服务 网关 】

单体架构时我们只需要完成一次用户登录、身份校验,就可以在所有业务中获取到用户信息。而微服务拆分后,每个微服务都独立部署,这就存在一些问题: 每个微服务都需要编写登录校验、用户信息获取的功能吗? 当微服务之间调…

Vue2之3v-model在组件中的应用以及sync修饰符

文章目录 v-model的原理带value属性组件间传值的普通写法解析演示 根据v-model的原理 简写带有value属性组件之间的传值解析演示 使用sync修饰符,自定义属性名进行组件传值解析案例 v-model的原理 v-model 原理 原理:v-model本质上是一个语法糖。例如应…

从0开始学vue:Element Plus详解

一、核心架构解析二、技术实现指南三、高级特性实现四、性能优化方案五、生态扩展方案六、调试与测试七、版本演进路线 Element Plus 是专为 Vue 3 设计的桌面端 UI 组件库,基于 Vue 3 的 Composition API 重构,在保持与 Element UI 兼容性的同时&#x…

Qt6使用opengl

1.使用qmloscilloscope工程 2.main函数里 bool openGLSupported QQuickWindow::graphicsApi() QSGRendererInterface::OpenGLRhi;if (!openGLSupported) { qWarning() << "OpenGL is not set as the graphics backend, so AbstractSeries.useOpenGL will not work…