8086中断指令列表
注意:列表列出的中断(
interrupt)现在都由仿真程序提供支持。这些中断应该在IBM PC和全系x86架构芯片、Intel 8086、AMD compatible microprocessors兼容。不过,Windows XP系统可能重写了一些原生的中断。
快速导航:
INT 10H/00H
INT 10H/01H
INT 10H/02H
INT 10H/03H
INT 10H/05H
INT 10H/06H
INT 10H/07H
INT 10H/08H
INT 10H/09H
INT 10H/0AH
INT 10H/0CH
INT 10H/0DH
INT 10H/0EH
INT 10H/13H
INT 10H/1003H
INT 11H
INT 12H
INT 13H/00H
INT 13H/02H
INT 13H/03H
INT 15H/86H
INT 16H/00H
INT 16H/01H
INT 19H
INT 1AH/00H
INT 20H
INT 21H
INT 21H/01H
INT 21H/02H
INT 21H/05H
INT 21H/06H
INT 21H/07H
INT 21H/09H
INT 21H/0AH
INT 21H/0BH
INT 21H/0CH
INT 21H/0EH
INT 21H/19H
INT 21H/25H
INT 21H/2AH
INT 21H/2CH
INT 21H/35H
INT 21H/39H
INT 21H/3AH
INT 21H/3BH
INT 21H/3CH
INT 21H/3DH
INT 21H/3EH
INT 21H/3FH
INT 21H/40H
INT 21H/41H
INT 21H/42H
INT 21H/47H
INT 21H/4CH
INT 21H/56H
INT 33H/0000H
INT 33H/0001H
INT 33H/0002H
INT 33H/0003H
INT 10H / AH = 0 设置图形(video)格式
输入:
AL = 希望的图形(video)模式
00H 文本模式 40 * 25 16色 8页
03H 文本模式 80 * 25 16色 8页
13H 图形模式 40 * 25 256色 320 * 200 像素 1页
示例:
MOV AL, 13H
MOV AH, 0
INT 10H
INT 10H / AH = 01H 设置文本模式光标形状
输入:
CH = 0-4位为光标开始线,5-7位为选项
CL = 0-4位底部光标线
CH 的第 5 位置为 0 光标可用,置为 1 时光标不可用。
示例:
; 隐藏闪烁的文本光标
MOV CH, 32
MOV AH, 1
INT 10H
; 显示标准闪烁文本光标
MOV CH, 6
MOV CL, 7
MOV AH, 1
INT 10H
; 显示箱状闪烁文本光标
MOV CH, 0
MOV CL, 7
MOV AH, 1
INT 10H
; 注意:一些 BIOS 要求 CL >= 7 否则会显示错误的光标形状
INT 10H / AH = 02H 设置光标位置
输入:
DH = 行
DL = 列
BH = 页数(0-7)
示例:
; 将光标位置设置在 0 页 10 行 20 列
MOV DH, 10
MOV DL, 20
MOV BH, 0
MOV AH, 2
INT 10H
INT 10H / AH = 03H 取得光标位置和尺寸
输入:
BH = 页数(0-7)
返回:
DH = 行
DL = 列
CH = 光标开始线
CL = 光标底部线
INT 10H / AH = 05H 设置活跃图形(video)页
输入:
AL = 新页数(0-7)
被激活的页面将会被显示。
INT 10H / AH = 06H(07H) 上(下)滚动窗口
输入:
AL = 想要滚动的行数(00H则清除整个窗口)
BL = 用于写窗口底部空白行的属性
CH, CL = 窗口左上角的行和列
DH, DL = 窗口右下角的行和列
INT 10H / AH = 08H 读取光标位置的字符和属性
输入:
BH = 页数
返回:
AH = 属性
AL = 字符
INT 10H / AH = 09H 将字符和属性写入光标位置
输入:
AL = 显示的字符
BH = 页数
BL = 属性
CX = 字符要写入的次数
INT 10H / AH = 0CH 对单一像素改变颜色
输入:
AL = 像素颜色
CX = 列
DX = 行
示例:
; 将图形(video)模式设置为图像模式
MOV AL, 13H
MOV AH, 0
INT 10H
; 将像素(20,10)颜色设置为 0CH
MOV AL, 0CH
MOV CX, 10
MOV DX, 20
MOV AH, 0CH
INT 10H
INT 10H / AH = 0DH 得到单个像素的颜色
输入:
CX = 列
DX = 行
返回:
AL = 像素颜色
INT 10H / AH = 0EH 电传打字机(teletype)输出
输入:
AL = 要写入的字符
这个中断在屏幕上显示字符,根据需要推动光标或滚动屏幕。通常都会显示在当前活跃页面。
示例:
MOV AL, 'a'
MOV AH, 0EH
INT 10H
; 注意:一些系统中这个中断在图形模式下不支持
INT 10H / AH = 13H 写入字符串
输入:
AL = 写入模式(第 0 位写入后更新光标;第 1 位字符中含有属性)
BH = 页数
BL = 如果字符串中只有字符的属性(AL第 1 位为0)
CX = 字符串中字符个数(属性不计算在内)
DL, DH = 开始写入的列,行
ES:BP = 要写入字符串的地址
示例:
MOV AL, 1
MOV BH, 0
MOV BL, 3BH
MOV CX, MSGEND - OFFSET MSG1 ; 计算字符串长度
MOV DL, 10
MOV DH, 7
PUSH CS
POP ES
MOV BP, OFFSET MSG1
MOV AH, 13H
INT 10H
JMP MSGEND
MSG1 DB "HELLO WORLD"
MSG1END:
INT 10H / AX = 1003H 常亮/闪烁 切换
输入:
BL = 写入模式(0为常亮模式,1为闪烁模式)
BH = 0(为了防止在一些适配器上出现问题)
示例:
MOV AX, 1003H
MOV BX, 0
INT 10H
位颜色表
字符属性是一个8位值,低四位前部颜色,高四位设置背景颜色。
注意:仿真器和 Windows 命令行不支持背景闪烁,然而为了使颜色在DOS和全屏环境下观感一致,还是要通过命令关闭背景闪烁。
| HEX | BIN | COLOR |
|---|---|---|
| 0 | 0000 | 黑色 |
| 1 | 0001 | 蓝色 |
| 2 | 0010 | 绿色 |
| 3 | 0011 | 青色 |
| 4 | 0100 | 红色 |
| 5 | 0101 | 洋红色 |
| 6 | 0110 | 棕色 |
| 7 | 0111 | 亮灰色 |
| 8 | 1000 | 暗灰色 |
| 9 | 1001 | 亮蓝色 |
| A | 1010 | 亮绿色 |
| B | 1011 | 亮青色 |
| C | 1100 | 亮红色 |
| D | 1101 | 亮洋红色 |
| E | 1110 | 黄色 |
| F | 1111 | 白色 |
注意:
; 使用这段代码保证DOS/CMD 全屏模式下的兼容性
MOV AX, 1003H
MOV BX, 0 ; 停止闪烁
INT 10H
INT 11H 取得BIOS设备列表
返回:
AX = BIOS 设备列表 字(word),事实上这个中断返回位于0040H:0010H的字的内容。
现今这个中断常用来确定设备安装的软盘个数。
各位代表 BIOS 检测 已安装硬件如下:
15-14 并行设备数量
13 预留
12 已安装游戏端口(用于连接卡带,手柄等游戏设备)
11-9 串行设备数量
8 预留
7-6 软盘数量(-1,即若为01,则有两个软盘)
5-4 初始图形(video)模式
00 EGA, VGA, PGA, 或其他在BIOS板的图形卡
01 40x25 CGA 彩色显示
10 80x25 CGA 彩色显示(默认)
11 80x25 纯文字(mono text)
3 预留
2 PS/2 接口的鼠标
1 已安装数学协处理器
0 当从软盘启动时设置(Set when booted from floppy)
例如,当DOSBOX执行INT 11H命令时,AX = D426H = 1101 0100 0010 0110B。则对于该虚拟机,有 3个并行设备,已安装 1 个游戏设备,两个串行设备,1个软盘,80x25 CGA 彩色显示,安装 PS/2 鼠标,安装数学协处理器,从软盘启动。
INT 12H 得到主存大小
返回
AX = 从绝对地址00000H处开始的相邻地址大小,以KB为单位,中断返回的是位于0040H:0013H处字的内容。
软盘通过使用 FLOPPY_0(..3) 文件仿真。
INT 13H / AH = 00H 重置磁盘系统
INT 13H / AH = 02H 将磁盘扇区读入主存
INT 13H / AH = 03H 写入磁盘扇区
输入:
AL = 需要读或写的扇区数(必须不为0)
CH = 柱面数(0-79)
CL = 扇区数(1-18)
DH = 磁头数(0-1)
DL = 驱动数(0-3,对于仿真器来说取决于 FLOPPY_file 的编号)
ES:BX = 数据缓冲区的地址
返回:
CF = 错误置1
CF = 成功置0
AH = 状态( 0 为成功)
AL = 转移的扇区数
由软盘的标准,一个扇区必须为 512B。
INT 15H / AH = 86H BIOS 等待中断
输入:
CX:DX = 以微秒为单位的间隔
返回:
CF = 0则成功(等待时间间隔流逝)
CF = 1则发送错误或等待中断已在进程
注意:在许多系统,等待时间的分辨率为977微秒(100万微妙-1秒)
Windows XP 系统不支持该中断(系统默认将CF恒置为1)
INT 16H / AH = 00H 从键盘取得按键(无回应)
返回:
AH = BIOS 扫描码
AL = ASCII 字符 (如果存在一个按键,将其从键盘缓冲区中移除)
INT 16H / AH = 01H 检查键盘缓冲区的按键
返回:
ZF = 1 若按键可用
ZF = 0 若按键不可用
AH = BIOS 扫描码
AL = ASCII 字符 (如果存在一个按键,将其从键盘缓冲区中移除)
INT 19H 系统重启
通常,BIOS会尝试从A盘读取0磁头,0磁道,1扇区到0000H:7C00H。仿真器仅停止其执行,从virtual drive -> boot from floppy菜单中选取的软盘启动。
INT 1AH / AH = 00H 得到系统时间
返回:
CX:DX = 从午夜(00:00)开始计算度过的时钟数
AL = 午夜计数器,每当度过一次午夜增加1
注意:一秒大约有18.24608个时钟周期,每天有
1800B0H个时钟周期,AL不是由仿真器设置的。
示例:
MOV AH, 00H
INT 1AH
在14:40时执行该程序,得到CX:DX=000EH:AA8BH,其值化为十进制为43883,化为分钟后约为40分钟。对于 DOSBOX 仿真器来说,午夜设置在了14:00。
INT 20H 退出操作系统
INT 21H MS-DOS 中断
DOS 的文件系统C:\emu8086\vdrive\x中仿真,这里的x是磁盘号。如果没有特殊指定磁盘号并且当前文件目录未设置,那么默认使用C:\emu8086\Mybuild\。FLOPPY_0, 1, 2, 3 文件从 DOS 文件系统独立仿真。
对于仿真器,物理磁盘A:为如下文件C:\emu8086\FLOPPY_0(支持 BIOS 中断 13H 并且启动)
对于 DOS 中断(INT 21H)A盘位于C:\emu8086\vdrive\a\仿真。
注意:DOS 文件系统限制文件和文件夹路径最多8字符,拓展名最多3字符;
例如如下有效1文件名
myfile.txt。拓展名写在点后,且不能有点。
INT 21H / AH = 01H 从标准输入读取字符,有回应,结果存在 AL。若键盘缓冲区无字符,中断等待直到有键被按下。
示例:
MOV AH, 01H
INT 21H
INT 21H / AH = 02H 写字符到标准输出
输入:
DL = 要写入的字符,执行后 AL = DL
示例:
MOV AH, 02H
MOV DL, 'a'
INT 21H
INT 21H / AH = 05H 输出字符到打印器
输入:
DL = 要打印的字符,执行后AL = DL
示例:
MOV AH, 05H
MOV DL, 'a'
INT 21H
INT 21H / AH = 06H 直接控制台输入/输出
输入:
DL = 输出 0-254(ASCII 码) 输入 255
返回:
输出时 AL = DL
输入时 若无字符可用则 ZF = 1 且 AL = 00H,若有字符可用则 ZF = 0
AL = 读取的字符;缓存区清除
示例:
; 输出字符
MOV AH, 06H
MOV DL, 'a'
INT 21H
; 从键盘缓冲区取得字符或置 ZF = 1
MOV AH, 06H
MOV DL, 255
INT 21H
INT 21H / AH = 07H 无回应输入字符到 AL
如果键盘缓冲区没有字符,则中断在有按键前等待
示例:
MOV AH, 07H
INT 21H
INT 21H / AH = 09H 输出位于DS:DX处的字符串,字符串必须由$终止
示例:
ORG 100H
MOV DX, OFFSET MSG
MOV AH, 09H
INT 21H
RET
MSG DB "hello world$"
INT 21H / AH = 0AH 输入一个字符到DS:DX,第一个字节为缓冲区大小,第二个字节是实际读取的字符数
这个中断不需要在字符串结尾加$。而用上一个中断必须要在结尾加入$并且从DS:DX + 2开始打印。
示例:
ORG 100H
MOV DX, OFFSET BUFFER
MOV AH, 0AH
INT 21H
JMP PRINT
BUFFER DB 10, ?, 10 DUP(' ')
PRINT:
XOR BX, BX ; BX = 0
MOV BL, BUFFER[1]
MOV BUFFER[BX+2] '$'
; 从 DS:DX + 2 处开始打印
MOV DX, OFFSET BUFFER + 2
MOV AH, 09H
INT 21H
RET
该中断不允许超出指定缓冲区大小字符进入。
INT 21H / AH = 0BH 取得输入状态
返回:
AL = 00H 如果没有字符可用;FFH如果有字符可用
INT 21H / AH = 0CH 清空键盘缓冲区并读取标准输入
输入:
AL = 清空缓存区后执行的输入中断编号(01H, 06H, 07H, 08H, 0AH,对其他值缓存区会被清空但不会有输入)
其他寄存器按照 AL 确定的中断进行设置。
INT 21H / AH = 0EH 选择默认磁盘
输入:
DL = 新的默认磁盘(0 对应A:\,1 对应B:\,...)
返回:
AL = 潜在有效盘符个数
注意:返回值是最高磁盘代表值(The highest drive present)
INT 21H / AH = 19H 取得现在默认磁盘
返回:
AL = 盘符(0 对应A:\,1 对应B:,...)
INT 21H / AH = 25H 设置中断向量
输入:
AL = 中断数
DS:DX = 新的中断执行句柄
INT 21H / AH = 2AH 取得系统时间
返回:
CX = 年(1980-2099)
DH = 月
DL = 日
AL = 星期(00H代表星期天)
INT 21H / AH = 2CH 取得系统时间
返回:
CH = 小时
CL = 分钟
DH = 秒
DL = 0.01秒
INT 21H / AH = 35H 取得中断向量
输入:
AL = 中断数
返回:
ES:BX = 现在中断句柄
INT 21H / AH = 39H 新建文件夹
输入:
DS:DX = ASCII 文件路径,最后以0结束字符串
返回:
CF = 0 则成功创建 AX 销毁,CF = 1 则发生错误,AX = 错误码
注意:除了最后一个路径可以不存在其他的必须存在
示例:
ORG 100H
MOV DX, OFFSET FILEPATH
MOV AH, 39H
INT 21H
RET
FILEPATH DB "C:\mydir", 0
END
上述代码如果在仿真器运行回创建C:\emu8086\vdrive\C\mydir文件夹。
INT 21H / AH = 3AH 删除文件夹
输入:
DS:DX = 要删除的文件夹路径,以0结束字符串
返回:
CF = 0 则成功删除 AX 销毁,CF = 1 则发生错误,AX = 错误码
要删除的文件夹必须存在且为空
INT 21H / AH = 3BH 设置当前路径
输入:
DS:DX = 要前往的路径(最大 64 字节)
返回:
CF = 0 成功,AX 销毁,CF = 1 发生错误,AX = 错误码
注意:即使新路径中包含盘符名,默认盘符也不会改变,只能前往该盘符下的路径
INT 21H / AH = 3CH 创建或删除(truncate)文件
输入:
MOV CX, 0 ; 正常,无属性
MOV CX, 1 ; 只读
MOV CX, 2 ; 隐藏
MOV CX, 4 ; 仅系统
MOV CX, 7 ; 只读,隐藏且仅系统
MOV CX, 16 ; 归档
DS:DX = 文件路径
返回:
CF = 0 则成功, AX = 文件句柄,CF = 1 发生错误,AX = 错误码
注意:若特定文件存在将会被不加警告地删除
示例:
ORG 100H
MOV AH, 3CH
MOV CX, 0
MOV DX, OFFSET FILENAME
MOV AH, 3CH
INT 21H
JC ERR
MOV HANDLE, AX
JMP K
FILENAME DB "myfile.txt", 0
HANDLE DW ?
ERR:
; ...
K:
RET
INT 21H / AH = 3DH
输入:
AL = 访问及共享模式
MOV AL, 0 ; 只读
MOV AL, 1 ; 只写
MOV AL, 2 ; 读写
DS:DX = 文件路径
返回:
CF = 0 则成功, AX = 文件句柄,CF = 1 发生错误,AX = 错误码
注意:文件指针会设置在文件开头;文件必须存在
示例:
ORG 100H
MOV AL, 2
MOV DX, OFFSET FILENAME
MOV AH, 3DH
INT 21H
JC ERR
MOV HANDLE, AX
JMP K
FILENAME DB "myfile.txt", 0
HANDLE DW ?
ERR:
; ...
K:
RET
INT 21H / AH = 3EH 关闭文件
输入:
BX = 文件句柄
返回:
CF = 0 则成功, AX = 文件句柄,CF = 1 发生错误,AX = 错误码(06H)
INT 21H / AH = 3FH 从文件读取
输入:
BX = 文件句柄
CX = 读取字节数
DS:DX = 数据缓冲区
返回:
CF = 0 则成功, AX = 实际读取字节数,AX = 0 调用前在EOF处
CF = 1 则发生错误,AX = 错误码
注意:数据从当前文件位置开始读取,并且在一次成功读取后文件位置会更新,如果发生局部分读取返回的 AX 可能比请求的字节数 CX 少
INT 21H / AH = 40H 写入文件
输入:
BX = 文件句柄
CX = 写入字节数
DS:DX = 要写入的数据
返回:
CF = 0 则成功, AX = 实际写入字节数,CF = 1 发生错误,AX = 错误码
若 CX = 0,没有数据写入,并且文件被缩短或扩展到当前位置数据,并且文件位置在成功写入后更新。通常使AX < CX的原因是磁盘已满
INT 21H / AH = 41H 删除文件(未连接的)
输入:
DS:DX = 文件路径(不能有通配符,请见注意)
返回:
CF = 0 则成功, AX 销毁,AL 为已删除文件的驱动,CF = 1 发生错误,AX = 错误码
注意:DOS不会擦除文件数据,仅变为不可访问。因为删除当前打开的文件时清除 FAT 链可能导致文件系统出错
INT 21H / AH = 42H 查找 设置当前文件位置
输入:
AL = 初始移动: 0 文件开始 1 当前文件位置 2 文件结束
BX = 文件句柄
CX:DX = 初始到新文件位置的偏移
返回:
CF = 0 则成功, DS:AX = 新文件位置(从问文件开始,以字节为单位),CF = 1 发生错误,AX = 错误码
这主意:对于初始的 1 和 2,指针可能指向文件开始之前;在这种状态下没有错误会被返回,但是虽有尝试读写文件会发生错误。若新的位置超过当前文件结尾,文件在下次写入时会被拓展(见 AH = 40H)
示例:
ORG 100H
; 创建文件
MOV AH, 3CH
MOV CX, 0
MOV DX, OFFSET FILENAME
MOV AH 3CH
INT 21H
; 写入文件
MOV BX, HANDLE
MOV DX, OFFSET DATA
MOV CX, DATA_SIZE
MOV AH, 40H
INT 21H
; 查找
MOV AL, 0
MOV BX, HANDLE
MOV CX, 0
MOV DX, 7
MOV AH, 42H
INT 21H
; 读取文件
MOV BX, HANDLE
MOV DX, OFFSET BUFFER
MOV CX, 4
MOV AH, 3FH
INT 21H
; 关闭文件
MOV BX, HANDLE
MOV AH, 3EH
INT 21H
RET
FILENAME DB "myfile.txt", 0
HANDLE DW ?
DATA DB "hello files!"
DATA_SIZE = $ - OFFSET DATA
BUFFER DB 4 DUP(' ')
INT 21H / AH = 47H 取得当前文件夹
输入:
DL = 盘符号(00H = 默认,01H = A:,...)
DS:SI = 用于存放路径的64位缓冲区去
返回:
CF = 0 则成功,CF = 1 发生错误,AX = 错误码(0FH)
返回的路径不包括盘符和初始反斜线
INT 21H / AH = 4CH 控制权交还操作系统(停止程序)
INT 21H / AH = 56H 移动/重命名文件
输入:
DS:DX = 已存在文件文件名
ES:DI = 新文件名
返回:
CF = 0 则成功,CF = 1 发生错误,AX = 错误码
注意:只允许在同一逻辑盘内移动;已打开文件不能重命名
INT 33H / AX = 0000 鼠标初始化,任何之前鼠标指针被隐藏
返回:
成功:AX = 0FFFFH BX = 鼠标按键个数
失败:AX = 0
示例:
MOV AX, 0
INT 33H
INT 33H / AX = 0001 显示鼠标指针
示例:
MOV AX, 1
INT 31H
INT 33H / AX = 0002 隐藏可见鼠标指针
示例:
MOV AX, 2
INT 33H
INT 33H / AX = 0003 取得鼠标位置和按键状态
返回:
若左键被按下,BX = 1
若右键被按下,BX = 2
若左键右键同时按下,BX = 3
CX = x
CY = y
示例:
; 注意:在 320x200 图形模式 CX 的值将加倍。
MOV AX, 3
INT 33H