8086汇编:如何自定义中断服务程序(ISR)?含中断向量表疑问
8086汇编自定义中断服务程序(ISR)指南
先搞懂中断向量表(IVT)
8086的中断向量表是内存最开头1KB的区域(地址0000:0000到0000:03FF),相当于CPU的“中断地址目录”:
- 每个中断号对应4字节的向量:前2字节是中断服务程序的偏移地址(IP),后2字节是段地址(CS)
- 对于中断号
n,它的向量起始地址是n×4,比如你提到的INT70(中断号70h,十六进制),向量地址是70h×4 = 1C0h:0000:01C0~0000:01C1存储ISR的IP0000:01C2~0000:01C3存储ISR的CS
自定义INT70的完整步骤
1. 编写中断服务程序(ISR)
ISR必须遵循固定规则:先保存用到的寄存器,执行自定义操作,最后用iret返回(不能用普通ret)。示例代码:
; INT70的中断服务程序 ISR_70: push ax ; 保存寄存器,避免破坏主程序的寄存器状态 push bx push dx ; 自定义操作:DOS下打印提示字符串 mov ah, 09h ; DOS功能调用:显示以$结尾的字符串 mov dx, offset MSG int 21h pop dx ; 恢复寄存器 pop bx pop ax iret ; 中断返回:自动弹出IP、CS、FLAGS,恢复现场 MSG db 'INT70 触发成功!$' ; 要显示的消息,必须以$结尾
2. 修改中断向量表,注册你的ISR
要把ISR的CS和IP写入IVT对应位置,注意修改时要关中断(防止中途被其他中断打断):
; 设置INT70的中断向量 setup_int70: cli ; 关中断,禁止其他中断干扰IVT修改 mov ax, 0 ; IVT位于0段 mov es, ax mov di, 70h * 4 ; 计算INT70的向量起始地址(70h×4=1C0h) mov ax, offset ISR_70 ; 取ISR的偏移地址(IP) stosw ; 写入IVT的前2字节(IP) mov ax, cs ; 取ISR所在的段地址(CS) stosw ; 写入IVT的后2字节(CS) sti ; 开中断,恢复中断响应 ret
3. 主程序调用自定义中断
在主程序中先完成中断向量注册,再调用INT70:
main: call setup_int70 ; 先注册INT70的中断向量 int 70h ; 调用自定义中断,执行ISR_70的代码 mov ah, 4Ch ; DOS功能调用:退出程序 int 21h
关键注意事项
- 寄存器保护:ISR必须保存所有它用到的寄存器(FLAGS除外),否则会破坏主程序的寄存器值,引发未知错误。
- 用iret返回:
iret会自动弹出栈中的IP、CS、FLAGS,完整恢复中断前的CPU状态,普通ret只弹出IP,无法正确收尾。 - 关中断时机:修改IVT时必须用
cli关中断,修改完成后用sti开中断,避免修改过程中CPU响应其他中断,读取不完整的向量地址。 - 中断号选择:尽量选择DOS未占用的中断号(比如
70h~77h通常保留给用户自定义),避免覆盖系统中断导致系统崩溃。
内容的提问来源于stack exchange,提问作者AnasNss11
相关产品推荐
相关产品推荐

