8088 INT1单步执行例程

发布时间:2026/5/27 8:36:04

8088 INT1单步执行例程 在Intel 8088处理器中INT 1是一个由硬件触发的特殊中断主要用于单步调试以逐条指令地追踪程序执行流程。它的工作关键在于CPU的标志寄存器中的陷阱标志位 (TF, Trap Flag)。简单来说当TF 1时CPU每执行完一条指令就会自动触发一个INT 1中断。要通过INT 1进行单步调试最关键的一步是设置陷阱标志TF。与INT 3有专用指令不同Intel 8088/8086 没有直接置位或清零TF的指令需要借助标志寄存器堆栈操作间接实现。以下是一个常见方法; 程序运行时TF默认被清零以下代码段将TF置为1 pushf ; 1. 将标志寄存器(F)的值压入堆栈 pop ax ; 2. 将堆栈顶的值弹出到AX寄存器中 or ax, 0100h ; 3. 将AX的第8位即TF位从0开始计数置为1 push ax ; 4. 将修改后的AX值压回堆栈 popf ; 5. 将堆栈顶的值弹出到标志寄存器(F)此时TF标志位即为1 ; 下一句指令执行后将触发单步中断 nop完整例程; 完整示例使用 INT 1 单步中断每执行一条指令自动触发一次中断 ; 汇编环境MASM/TASM运行于 DOS或模拟器如 DOSBox ; 目标处理器Intel 8088 .model small .stack 100h .code ; 步数计数器与最大步数存储在代码段通过 CS 访问避免依赖 DS step_count dw 0 max_steps dw 5 ; 启动与结束提示字符串存储在数据段 .data msg_start db Starting single step..., 13, 10, $ msg_done db Done., 13, 10, $ .code ; ------------------------------------------------------------------ ; 自定义 INT 1 中断服务程序 ; 功能显示当前步数当步数达到 max_steps 时清除 TF 标志以停止单步 ; ------------------------------------------------------------------ int1_handler proc ; 保存所有寄存器8088 无 pusha逐一保存 push ax push bx push cx push dx push si push di push ds push es ; 增加步数计数器变量在代码段使用 CS 前缀 inc cs:step_count ; 显示步数简单数字由于步数 ≤5直接输出个位 mov dx, cs:step_count add dl, 0 cmp dl, 9 jle ok_digit mov dl, ? ; 防错实际不会触发 ok_digit: mov ah, 0Eh ; BIOS 字符输出Teletype int 10h mov dl, ; 输出空格分隔 int 10h ; 检查是否达到最大步数 mov ax, cs:step_count cmp ax, cs:max_steps jl no_disable ; 达到最大步数清除堆栈中原标志寄存器的 TF 位第 8 位 ; 堆栈布局进入 ISR 后[AX][BX][CX][DX][SI][DI][DS][ES] 原始 IP 原始 CS 原始 FLAGS ; 当前 SP 指向 ES原始 FLAGS 位于 [SP 20] 处 mov bx, sp add bx, 20 and word ptr [bx], 0FEFFh ; 清零 TF 位0xFEFF 1111111011111111 no_disable: ; 恢复寄存器 pop es pop ds pop di pop si pop dx pop cx pop bx pop ax iret int1_handler endp ; ------------------------------------------------------------------ ; 主程序 ; ------------------------------------------------------------------ main proc mov ax, data mov ds, ax ; 设置数据段用于输出字符串 ; 保存原 INT 1 中断向量 xor ax, ax mov es, ax mov ax, es:[4 * 1] ; 偏移地址 mov bx, es:[4 * 1 2] ; 段地址 mov cs:old_int1_off, ax mov cs:old_int1_seg, bx ; 设置新的 INT 1 中断向量 cli ; 关中断避免设置过程被打断 mov es:[4 * 1], offset int1_handler mov es:[4 * 1 2], cs sti ; 显示启动信息 mov dx, offset msg_start mov ah, 9 int 21h ; 开启陷阱标志 TF启用单步模式 pushf pop ax or ax, 0100h ; 置 TF 位第 8 位 push ax popf ; 被单步跟踪的指令序列 nop ; 第 1 步 nop ; 第 2 步 mov ax, 1234h ; 第 3 步 add ax, 1 ; 第 4 步 sub ax, bx ; 第 5 步执行后 ISR 会清除 TF后续不再触发 ; ; 显示完成信息 mov dx, offset msg_done mov ah, 9 int 21h ; 恢复原 INT 1 中断向量 cli xor ax, ax mov es, ax mov ax, cs:old_int1_off mov bx, cs:old_int1_seg mov es:[4 * 1], ax mov es:[4 * 1 2], bx sti ; 返回 DOS mov ah, 4Ch int 21h old_int1_off dw ? old_int1_seg dw ? main endp end main运行效果程序启动后显示Starting single step...随后每执行一条指令屏幕上依次显示步数1 2 3 4 5最后显示Done.并退出。关键说明设置陷阱标志TF通过pushf/popf间接修改 TF 位没有直接指令可操作。中断服务程序记录步数、输出字符并在步数达到上限时修改堆栈中保存的标志寄存器清除 TF 位使后续指令不再触发单步。堆栈操作ISR 中需正确计算原始 FLAGS 在堆栈中的位置进入 ISR 后 CPU 已压入 FLAGS、CS、IP加上 ISR 保存的 8 个寄存器共 16 字节偏移 20 字节即指向原始 FLAGS。安全考虑ISR 使用 BIOS 中断INT 10h输出避免调用可能重入的 DOS 功能变量置于代码段并用CS:前缀访问确保不依赖数据段寄存器。此示例完整展示了INT 1在 8088 上的典型用法——实现单步调试跟踪。

相关新闻