求组DeepSeek给的将要进行的8088单板机NMI中断编程示例。
/* nmidemo.c - 8088 单板机 NMI 中断演示程序 */
/* 脱离 DOS 环境,直接运行在裸机上 */
/* 使用 Digital Mars C 编译器,TINY 模式编译 *//* 硬件配置假设:- 8088 CPU @ 4.77MHz- 8255 PPI (可编程外设接口) 连接 LED- NMI 按钮连接到 NMI 引脚- 系统 ROM 从 0xF0000 开始 *//* 端口定义 */
#define PORT_PPI_A 0x60 // 8255 PPI 端口 A (LED 控制)
#define PORT_PPI_B 0x61 // 8255 PPI 端口 B
#define PORT_PPI_C 0x62 // 8255 PPI 端口 C
#define PORT_PPI_CTRL 0x63 // 8255 PPI 控制端口/* 函数声明 */
void nmi_handler(void);
void set_nmi_handler(void);
void init_ppi(void);
void delay(unsigned int count);
void outportb(unsigned short port, unsigned char value);
unsigned char inportb(unsigned short port);/* NMI 计数器 */
volatile unsigned char nmi_count = 0;/* 主函数 */
int main() {// 设置栈指针 (在 64KB RAM 顶部)asm {mov ax, csmov ss, axmov sp, 0xFFFE}// 初始化硬件init_ppi();set_nmi_handler();// 初始状态: 点亮 LED 0outportb(PORT_PPI_A, 0x01);// 主循环 - 等待 NMIwhile (1) {// 循环点亮 LEDfor (int i = 0; i < 8; i++) {outportb(PORT_PPI_A, 1 << i);delay(0xFFFF);}}return 0;
}/* 设置 NMI 处理程序 */
void set_nmi_handler() {// 保存原始 NMI 向量 (中断号 2)unsigned int nmi_vector = 2 * 4; // 每个中断向量占 4 字节// 获取原始 NMI 处理程序地址unsigned int orig_offset, orig_segment;asm {push dsxor ax, axmov ds, axmov si, [nmi_vector]mov [orig_offset], simov si, [nmi_vector+2]mov [orig_segment], sipop ds}// 设置新的 NMI 处理程序asm {push dsxor ax, axmov ds, axmov si, [nmi_vector]mov word ptr [si], offset nmi_handlermov si, [nmi_vector+2]mov [si], cs ; 段地址 = CSpop ds}// 启用 NMI (清除 CMOS 寄存器第 7 位)outportb(0x70, inportb(0x70) & 0x7F);
}/* NMI 中断处理程序 */
void nmi_handler() {// 保存寄存器asm {push axpush bxpush cxpush dxpush ds}// 设置数据段asm {mov ax, csmov ds, ax}// 增加 NMI 计数器nmi_count++;// 在 LED 上显示 NMI 发生 (二进制计数)outportb(PORT_PPI_A, nmi_count);// 延迟一段时间 (视觉反馈)delay(0xFFFF);// 恢复寄存器asm {pop dspop dxpop cxpop bxpop ax}// 中断返回asm iret;
}/* 初始化 8255 PPI */
void init_ppi() {// 设置 8255 控制字: 端口 A 输出, 模式 0outportb(PORT_PPI_CTRL, 0x80); // 10000000b: 端口 A 输出, 端口 B 输出, 端口 C 输出// 初始状态: 关闭所有 LEDoutportb(PORT_PPI_A, 0x00);
}/* 端口输出函数 */
void outportb(unsigned short port, unsigned char value) {asm {mov dx, portmov al, valueout dx, al}
}/* 端口输入函数 */
unsigned char inportb(unsigned short port) {unsigned char value;asm {mov dx, portin al, dxmov value, al}return value;
}/* 简单延迟函数 */
void delay(unsigned int count) {asm {mov cx, countdelay_loop:noploop delay_loop}
}