惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
Google Online Security Blog
Google Online Security Blog
月光博客
月光博客
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
The Cloudflare Blog
Blog — PlanetScale
Blog — PlanetScale
F
Full Disclosure
G
Google Developers Blog
罗磊的独立博客
Jina AI
Jina AI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
A
About on SuperTechFans
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
GbyAI
GbyAI
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
The Register - Security
The Register - Security
U
Unit 42
D
Docker
Martin Fowler
Martin Fowler
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
博客园_首页
Google DeepMind News
Google DeepMind News

faryou的博客

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】再谈栈 【汇编基础教程】段 【汇编基础教程】来存一些数据! 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来写个“函数” 【汇编基础教程】更灵活的定位内存 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):背包DP——程序设计思路与代码实现 【算法教程】【C/C++】DP(动态规划):简单动规问题——程序设计思路与代码实现 【算法教程】【C/C++】递推——程序设计思路与代码实现 【算法教程】【C/C++】三分算法——程序设计思路与代码实现 【算法教程】【C/C++】二分答案——程序设计思路与代码实现 【算法教程】【C/C++】二分查找——程序设计思路与代码实现 【算法教程】【C/C++】贪心算法——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快排——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:快速幂——程序设计思路与代码实现 【算法教程】【C/C++】基础数学:进制转换——程序设计思路与代码实现 一文弄懂C++中的自定义函数 faryou的博客-2024年度总结
【汇编&硬件】屏幕输出中断的具体实现
作者: faryou · 2026-02-27 · via faryou的博客

前言

在8086汇编中,屏幕输出常用的中断是int 10h(BIOS视频服务中断),其功能涵盖文字模式(如文本显示)和图形模式(可模拟简单视频输出)。以下实现一个模拟int 10h核心功能的自定义屏幕输出中断程序,支持文字模式字符显示、光标控制和图形模式像素点绘制,并添加详细注释。

代码实现

; 常量定义
VIDEO_SEG_TEXT equ 0b800h ; 文本模式显存段地址(80x25彩色文本)
VIDEO_SEG_GRAPH equ 0a000h ; 图形模式显存段地址(320x200 256色)
MAX_ROW_TEXT equ 24 ; 文本模式最大行号(0-24)
MAX_COL_TEXT equ 79 ; 文本模式最大列号(0-79)
CURSOR_PORT_H equ 03d4h ; 光标控制端口(高8位)
CURSOR_PORT_L equ 03d5h ; 光标控制端口(低8位)
 
code segment
    assume cs:code, ds:data
 
; 自定义屏幕输出中断服务程序(入口:AH=功能号)
; 功能:
; AH=00h:设置显示模式(0=文本模式,13h=320x200图形模式)
; AH=02h:设置光标位置(BH=页号,DH=行,DL=列)
; AH=09h:在当前位置显示字符(AL=字符,BH=页号,BL=属性,CX=重复次数)
; AH=0Ch:图形模式画点(AL=颜色,CX=X坐标,DX=Y坐标)
video_int proc far
    push ax
    push bx
    push cx
    push dx
    push si
    push di
    push es
    push ds ; 保存所有寄存器
    push bp
    mov bp, sp ; 建立栈帧(便于访问参数)
 
    ; 读取功能号(AH),跳转至对应处理逻辑
    cmp ah, 00h
    je set_mode ; 设置显示模式
    cmp ah, 02h
    je set_cursor ; 设置光标位置
    cmp ah, 09h
    je print_char ; 文本模式显示字符
    cmp ah, 0Ch
    je draw_pixel ; 图形模式画点
    jmp int_end ; 不支持的功能,直接返回
 
; 功能00h:设置显示模式
; 入口:AL=模式号(0=80x25文本,13h=320x200图形)
set_mode:
    ; 保存当前模式(实际中可存入内存变量)
    mov [current_mode], al
    ; 调用BIOS原int 10h完成硬件模式切换(简化处理,实际需直接操作显卡端口)
    int 10h
    jmp int_end
 
; 功能02h:设置光标位置(仅文本模式有效)
; 入口:BH=页号(文本模式),DH=行号,DL=列号
set_cursor:
    ; 检查当前模式是否为文本模式(0)
    cmp byte ptr [current_mode], 0
    jne int_end ; 非文本模式不处理
 
    ; 计算光标位置(80列/行,公式:位置=行*80 + 列)
    mov al, dh ; AL=行号
    mov cl, 80 ; CL=每行字符数
    mul cl ; AX=行*80
    add ax, dx ; AX=行*80 + 列(光标位置)
 
    ; 向光标端口写入位置(高8位+低8位)
    mov dx, CURSOR_PORT_H ; 端口:光标高8位
    mov al, 0Eh ; 命令:设置光标高8位
    out dx, al
    mov dx, CURSOR_PORT_L ; 端口:光标低8位
    mov al, ah ; 高8位数据
    out dx, al
 
    mov dx, CURSOR_PORT_H
    mov al, 0Fh ; 命令:设置光标低8位
    out dx, al
    mov dx, CURSOR_PORT_L
    mov al, al ; 低8位数据(AX低8位)
    out dx, al
    jmp int_end
 
; 功能09h:文本模式显示字符
; 入口:AL=字符,BH=页号,BL=属性(高4位背景,低4位前景),CX=重复次数
print_char:
    cmp byte ptr [current_mode], 0
    jne int_end ; 非文本模式不处理
 
    ; 获取当前光标位置(简化:从内存变量读取,实际应读光标端口)
    mov dh, [cursor_row] ; DH=当前行
    mov dl, [cursor_col] ; DL=当前列
 
    ; 计算显存地址:文本模式显存 = 0b800h:[(行*80 + 列)*2]
    mov ax, VIDEO_SEG_TEXT
    mov es, ax ; ES=显存段地址
    mov al, dh
    mov cl, 80
    mul cl ; AX=行*80
    add ax, dx ; AX=行*80 + 列
    shl ax, 1 ; AX=地址偏移量(每个字符占2字节:ASCII+属性)
    mov di, ax ; DI=显存偏移
 
    ; 循环显示字符(CX=重复次数)
print_loop:
    mov es:[di], al ; 写入字符ASCII码
    mov es:[di+1], bl ; 写入属性(颜色)
    add di, 2 ; 下一个字符位置
    inc dl ; 列号+1
    cmp dl, MAX_COL_TEXT+1 ; 判断是否超出列边界
    jle next_char
    mov dl, 0 ; 列号归零
    inc dh ; 行号+1
    cmp dh, MAX_ROW_TEXT+1 ; 判断是否超出行边界
    jle next_char
    mov dh, 0 ; 行号归零(滚屏简化处理)
next_char:
    loop print_loop
 
    ; 更新光标位置
    mov [cursor_row], dh
    mov [cursor_col], dl
    jmp int_end

; 功能0Ch:图形模式画点(320x200 256色)
; 入口:AL=颜色,CX=X坐标(0-319),DX=Y坐标(0-199)
draw_pixel:
    cmp byte ptr [current_mode], 13h
    jne int_end ; 非13h图形模式不处理
 
    ; 计算像素地址:320x200模式下,地址=Y*320 + X
    mov ax, VIDEO_SEG_GRAPH
    mov es, ax ; ES=图形显存段地址
    mov ax, dx ; AX=Y坐标
    mov bx, 320
    mul bx ; AX=Y*320
    add ax, cx ; AX=Y*320 + X(像素偏移量)
    mov di, ax ; DI=显存偏移
    mov es:[di], al ; 写入颜色值
    jmp int_end
 
; 中断结束:恢复寄存器并返回
int_end:
    pop bp
    pop ds
    pop es
    pop di
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    iret ; 中断返回
video_int endp
 
; 安装自定义中断向量(替换int 10h)
install proc
    cli ; 关中断,防止安装过程被打断
    mov ax, 0
    mov es, ax ; ES指向中断向量表(0段)
    mov di, 10*4 ; int 10h的向量地址:10*4=40(0000:0028)
    mov ax, offset video_int ; 中断服务程序偏移地址
    stosw ; 写入偏移量到向量表
    mov ax, cs ; 中断服务程序段地址(当前代码段)
    stosw ; 写入段地址到向量表
    sti ; 开中断
    ret
install endp
 
; 主程序:初始化并测试自定义中断
main:
    mov ax, data
    mov ds, ax ; 初始化数据段
 
    call install ; 安装自定义屏幕输出中断
 
    ; 测试1:设置文本模式(00h)
    mov ah, 00h
    mov al, 00h
    int 10h ; 调用自定义中断
 
    ; 测试2:显示字符"Hello, World!"(文本模式)
    mov ah, 09h
    mov al, 'H'
    mov bl, 07h ; 属性:黑底白字
    mov cx, 1
    int 10h
    ; 此处可继续添加其他字符的显示代码...
 
    ; 测试3:切换到图形模式(13h)并画点
    mov ah, 00h
    mov al, 13h
    int 10h
    mov ah, 0Ch
    mov al, 0Ch ; 颜色:红色
    mov cx, 100 ; X=100
    mov dx, 50 ; Y=50
    int 10h ; 画点
 
    jmp $ ; 无限循环,保持程序运行
 
code ends
 
; 数据段:保存当前模式和光标位置
data segment
    current_mode db 0 ; 当前显示模式(0=文本,13h=图形)
    cursor_row db 0 ; 当前光标行号
    cursor_col db 0 ; 当前光标列号
data ends
 
    end main

代码说明

  1. 中断功能设计:模拟int 10h的核心功能,包括显示模式设置(文本/图形)、光标控制、文本字符显示和图形像素绘制,覆盖基本屏幕输出需求。
  2. 文本模式实现:a.显存地址为 0b800h ,每个字符占2字节(低字节为ASCII码,高字节为属性,控制前景/背景色)。b.光标位置通过显卡端口 03d4h 和 03d5h 设置,计算方式为 行号×80 + 列号 (80列文本模式)。
  3. 图形模式实现:- 320x200 256色模式的显存地址为 0a000h ,每个像素直接对应一个字节(存储颜色值),地址计算为 Y×320 + X 。
  4. 中断安装:通过修改中断向量表(0段)中int 10h的入口地址,将其指向自定义服务程序,安装时需关中断( cli )保证操作原子性。
  5. 测试逻辑:主程序安装中断后,依次测试文本模式字符显示和图形模式画点功能,验证中断有效性。