You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用户态触发中断时显存未写入,出现int 13错误码18问题排查

用户态触发中断时显存未写入的问题

问题描述

用户态代码通过int指令触发中断后,中断处理程序本应在屏幕上显示'A',但实际未生效。反而屏幕上出现的是int 13错误码18的提示,问题似乎出在将ds切换为内核段的步骤中。

中断处理程序代码

void irsHandler(intData data)
{
    char* vm = (char*) 0xb8000;
    vm[0] = 'A';
}

更新信息

GDT定义

gdt_start:
;first entry is always null (each entry is 8 bytes or 64 bits)
dd 0x0 ; 4 byte
dd 0x0 ; 4 byte

; GDT for code segment. base = 0x00000000, length = 0xfffff
gdt_code: 
dw 0xFFFF   ; segment length, bits 0-15
dw 0x0       ; segment base, bits 0-15
db 0x0       ; segment base, bits 16-23
db 10011010b ; flags (8 bits)
db 11000000b ; flags (4 bits) + segment length, bits 16-19
db 0x0       ; segment base, bits 24-31

; GDT for data segment. base and length identical to code segment
gdt_data:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11000000b
db 0x0

U_code: 
dw 0xFFFF    ; segment length, bits 0-15
dw 0x6000    ; segment base, bits 0-15
db 0x00      ; segment base, bits 16-23
db 11111010b ; flags (8 bits)
db 11000111b ; flags (4 bits) + segment length, bits 16-19
db 0x00       ; segment base, bits 24-31

; 用户态数据段
U_data:
dw 0xFFFF
dw 0x6000
db 0x00
db 11110010b
db 11000111b
db 0x00

gdt_tss:
dw TSS_SIZE-1      ; segment length, bits 0-15
dw tss             ; segment base, bits 0-15
db 0x0             ; segment base, bits 16-23
db 10001001b       ; access flags (8 bits)
db 00000000b       ; flags (4 bits) + segment length, bits 16-19
db 0x0             ; segment base, bits 24-31

gdt_end:

; GDT descriptor
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size
dd gdt_start ; address (32 bit)

调用C处理程序的汇编Stub

isr_common_stub:
pusha ; 将通用寄存器压栈

mov ax, ds ; eax低16位 = ds
push eax ; 保存数据段描述符

mov ax, 0x10  ; 内核数据段描述符
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

call irsHandler ; 调用C处理函数

pop eax 
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

popa
add esp, 8 ; 清理压入的错误码和ISR编号
sti
iret

可能的原因分析

  • 栈平衡问题:add esp,8的操作需要对应中断触发时栈上的内容。如果触发的中断本身没有错误码,却执行了该操作,会导致栈指针偏移错误,后续iret执行时会读取错误的返回地址/段选择子,引发异常。
  • TSS配置错误:从用户态进入内核态时,CPU依赖TSS切换到内核栈。如果TSS未正确初始化或加载,会导致栈切换失败,触发异常进而出现int 13错误。
  • 中断向量表配置错误:若触发的中断对应的向量未指向isr_common_stub,可能意外触发了int 13的处理逻辑,而非目标中断程序。
  • 段切换异常:切换ds到内核段(0x10)时,若栈中保存的用户态ds值无效,或切换过程中出现权限冲突,会引发段异常,中断原处理流程。
  • 显存访问未生效:即使切换到内核段,若irsHandler因栈异常或函数调用约定不匹配未被正确执行,写入显存的代码根本没运行,自然不会显示'A'。

内容的提问来源于stack exchange,提问作者Jacob Knuth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 05:42:58