X86系统中断处理与特权级转移 软中断实现系统调用 用户态程序使用软中断扎内核调用内核态程序
2022/1/29 22:05:04
本文主要是介绍X86系统中断处理与特权级转移 软中断实现系统调用 用户态程序使用软中断扎内核调用内核态程序,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
不会,中断整体是由 处理器 与 8259A中断控制器 共同管理的,虽然8259A可以不停的将中断请求发送给处理器,但是处理器有屏蔽中断的开关,只要当前中断处理还没有完成,就可以将IF置0 即不接受其他中断请求。
处理器没有中断优先级的概念,它只有响应与不响应的概念,当在执行中断处理时,屏蔽外部中断请求时 不响应8259A发来的中断请求。相反 当中断服务程序完成时,重新开始响应8259A的中断请求。
处理器拿到中断向量之后,就会到中断描述符表中查找对应的中断向量,进而找到一个中断描述符,然后继续特权级检查,最后将目标代码段的选择子加载到 cs寄存器,将中断服务程序的偏移地址加载的 ip寄存器,之后就可以执行 中断服务程序了。
低特权级用户态代码段 执行软中断,此时就会发生特权级转移,转移到高特权级内核态代码段执行,此时 栈就会发生变化,既然特权级要转移到高特权级,那么栈就要使用高特权级的栈,于是相关的寄存器就要入栈,包括ss寄存器(栈基地址) esp寄存器(栈顶指针) 这两个寄存器信息 就是指向了 低特权级的栈,将这些寄存器值 压入高特权级栈中,标志寄存器的值也要入栈(eflags),然后返回地址也要入栈,即 cs寄存器的值 以及ip寄存器的值 也要入栈。至此 就可以取执行中断服务程序了,此时 cs寄存器指向了 内核态代码段, ip寄存器指向了 中断服务程序偏移地址,组合就是中断服务程序的入口地址,然后开始执行中断服务程序,执行到遇到 iret指令后 返回。所以 iret指令执行后 使处理器从内核态 返回到 用户态 ,即从高特权级代码段 切换到 低特权级代码段。
inc.asm
; PIC-8259A Ports MASTER_ICW1_PORT equ 0x20 MASTER_ICW2_PORT equ 0x21 MASTER_ICW3_PORT equ 0x21 MASTER_ICW4_PORT equ 0x21 MASTER_OCW1_PORT equ 0x21 MASTER_OCW2_PORT equ 0x20 MASTER_OCW3_PORT equ 0x20 SLAVE_ICW1_PORT equ 0xA0 SLAVE_ICW2_PORT equ 0xA1 SLAVE_ICW3_PORT equ 0xA1 SLAVE_ICW4_PORT equ 0xA1 SLAVE_OCW1_PORT equ 0xA1 SLAVE_OCW2_PORT equ 0xA0 SLAVE_OCW3_PORT equ 0xA0 MASTER_EOI_PORT equ 0x20 MASTER_IMR_PORT equ 0x21 MASTER_IRR_PORT equ 0x20 MASTER_ISR_PORT equ 0x20 SLAVE_EOI_PORT equ 0xA0 SLAVE_IMR_PORT equ 0xA1 SLAVE_IRR_PORT equ 0xA0 SLAVE_ISR_PORT equ 0xA0 ; Segment Attribute DA_32 equ 0x4000 DA_LIMIT_4K EQU 0x8000 DA_DR equ 0x90 DA_DRW equ 0x92 DA_DRWA equ 0x93 DA_C equ 0x98 DA_CR equ 0x9A DA_CCO equ 0x9C DA_CCOR equ 0x9E ; Segment Privilege DA_DPL0 equ 0x00 ; DPL = 0 DA_DPL1 equ 0x20 ; DPL = 1 DA_DPL2 equ 0x40 ; DPL = 2 DA_DPL3 equ 0x60 ; DPL = 3 ; Special Attribute DA_LDT equ 0x82 DA_TaskGate equ 0x85 ; 任务门类型值 DA_386TSS equ 0x89 ; 可用 386 任务状态段类型值 DA_386CGate equ 0x8C ; 386 调用门类型值 DA_386IGate equ 0x8E ; 386 中断门类型值 DA_386TGate equ 0x8F ; 386 陷阱门类型值 ; Selector Attribute SA_RPL0 equ 0 SA_RPL1 equ 1 SA_RPL2 equ 2 SA_RPL3 equ 3 SA_TIG equ 0 SA_TIL equ 4 PG_P equ 1 ; 页存在属性位 PG_RWR equ 0 ; R/W 属性位值, 读/执行 PG_RWW equ 2 ; R/W 属性位值, 读/写/执行 PG_USS equ 0 ; U/S 属性位值, 系统级 PG_USU equ 4 ; U/S 属性位值, 用户级 ; 描述符 ; usage: Descriptor Base, Limit, Attr ; Base: dd ; Limit: dd (low 20 bits available) ; Attr: dw (lower 4 bits of higher byte are always 0) %macro Descriptor 3 ; 段基址, 段界限, 段属性 dw %2 & 0xFFFF ; 段界限1 dw %1 & 0xFFFF ; 段基址1 db (%1 >> 16) & 0xFF ; 段基址2 dw ((%2 >> 8) & 0xF00) | (%3 & 0xF0FF) ; 属性1 + 段界限2 + 属性2 db (%1 >> 24) & 0xFF ; 段基址3 %endmacro ; 共 8 字节 ; 门 ; usage: Gate Selector, Offset, DCount, Attr ; Selector: dw ; Offset: dd ; DCount: db ; Attr: db %macro Gate 4 dw (%2 & 0xFFFF) ; 偏移地址1 dw %1 ; 选择子 dw (%3 & 0x1F) | ((%4 << 8) & 0xFF00) ; 属性 dw ((%2 >> 16) & 0xFFFF) ; 偏移地址2 %endmacro
loader.asm
%include "inc.asm" org 0x9000 jmp ENTRY_SEGMENT ;全局段描述符表 [section .gdt] ; GDT definition ; 段基址, 段界限, 段属性 GDT_ENTRY : Descriptor 0, 0, 0 ;用户代码段 段描述符 3特权级 32位可执行代码段 3特权级 CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_C + DA_32 + DA_DPL3 VIDEO_DESC : Descriptor 0xB8000, 0x07FFF, DA_DRWA + DA_32 + DA_DPL3 DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_DRW + DA_32 + DA_DPL3 ;特权级3栈段 描述符 3特权级 STACK32U_DESC : Descriptor 0, TopOfStack32U, DA_DRW + DA_32 + DA_DPL3 ;特权级0栈段 描述符 0特权级 STACK32K_DESC : Descriptor 0, TopOfStack32K, DA_DRW + DA_32 + DA_DPL0 ;TSS任务状态段 段描述符 0特权级 TSS_DESC : Descriptor 0, TSSLen - 1, DA_386TSS + DA_DPL0 ;内核代码段 段描述符 0特权级 32位可执行代码段 0特权级 KERNEL32_DESC : Descriptor 0, Kernel32SegLen - 1, DA_C + DA_32 + DA_DPL0 ; GDT end GdtLen equ $ - GDT_ENTRY GdtPtr: dw GdtLen - 1 dd 0 ; GDT Selector ;用户态代码段 段描述符 选择子 Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL3 VideoSelector equ (0x0002 << 3) + SA_TIG + SA_RPL3 Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL3 ;特权级3栈段描述符 选择子 Stack32USelector equ (0x0004 << 3) + SA_TIG + SA_RPL3 ;特权级0栈段描述符 选择子 Stack32KSelector equ (0x0005 << 3) + SA_TIG + SA_RPL0 ;TSS任务状态段 段描述符选择子 TSSSelector equ (0x0006 << 3) + SA_TIG + SA_RPL0 ;内核代码段 段描述符 选择子 Kernel32Selector equ (0x0007 << 3) + SA_TIG + SA_RPL0 ; end of [section .gdt] ;中断描述符表 每一个中断描述符(中断门)特权级都是3 当做蹦床 跳转到 更高特权级代码段 类似于调用门 [section .idt] align 32 [bits 32] IDT_ENTRY: ; IDT definition ; Selector, Offset, DCount, Attribute %rep 32 Gate Kernel32Selector, DefaultHandler, 0, DA_386IGate + DA_DPL3 %endrep Int0x20 : Gate Kernel32Selector, TimerHandler, 0, DA_386IGate + DA_DPL3 %rep 95 Gate Kernel32Selector, DefaultHandler, 0, DA_386IGate + DA_DPL3 %endrep Int0x80 : Gate Kernel32Selector, Int0x80Handler, 0, DA_386IGate + DA_DPL3 %rep 127 Gate Kernel32Selector, DefaultHandler, 0, DA_386IGate + DA_DPL3 %endrep IdtLen equ $ - IDT_ENTRY ;中断描述符表所对应的指针结构 IdtPtr: dw IdtLen - 1 ;界限 dd 0 ;起始位置 暂时为0 后面初始化 ; end of [section .idt] TopOfStack16 equ 0x7c00 ;TSS任务状态段 本质上也是一块内存,所以也需要遵循32位保护模式的编程规则,需要定义对应的段描述符+选择子 [section .tss] [bits 32] TSS_SEGMENT: dd 0 dd TopOfStack32K ; 0 特权级对应的栈信息:栈顶指针 dd Stack32KSelector ; 0 特权级对应的栈信息:栈段基指针 dd 0 ; 1 特权级对应的栈信息 暂时为空 dd 0 ; dd 0 ; 2 特权级对应的栈信息 暂时为空 dd 0 ; times 4 * 18 dd 0 ; 往下全部定义为0,因为次实验不涉及多任务切换,所以不需要使用那些保存寄存器值的字段 dw 0 dw $ - TSS_SEGMENT + 2 db 0xFF ; 结束符 TSSLen equ $ - TSS_SEGMENT [section .dat] [bits 32] DATA32_SEGMENT: DTOS db "D.T.OS!", 0 DTOS_OFFSET equ DTOS - $$ INT_80H db "int 0x80", 0 INT_80H_OFFSET equ INT_80H - $$ Data32SegLen equ $ - DATA32_SEGMENT [section .s16] [bits 16] ENTRY_SEGMENT: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, TopOfStack16 ;初始化用户代码段 段描述符 mov esi, CODE32_SEGMENT mov edi, CODE32_DESC call InitDescItem mov esi, DATA32_SEGMENT mov edi, DATA32_DESC call InitDescItem ;初始化 特权级3 栈段 段描述符 mov esi, STACK32U_SEGMENT mov edi, STACK32U_DESC call InitDescItem ;初始化 特权级0 栈段 段描述符 mov esi, STACK32K_SEGMENT mov edi, STACK32K_DESC call InitDescItem ;初始化TSS段 mov esi, TSS_SEGMENT mov edi, TSS_DESC call InitDescItem ;初始化内核代码段 段描述符 mov esi, KERNEL32_SEGMENT mov edi, KERNEL32_DESC call InitDescItem ; initialize GDT pointer struct mov eax, 0 mov ax, ds shl eax, 4 add eax, GDT_ENTRY mov dword [GdtPtr + 2], eax ; initialize IDT pointer struct mov eax, 0 mov ax, ds shl eax, 4 add eax, IDT_ENTRY mov dword [IdtPtr + 2], eax ; 1. load GDT lgdt [GdtPtr] ; 2. close interrupt ; load IDT ; set IOPL to 3 cli lidt [IdtPtr] pushf pop eax or eax, 0x3000 push eax popf ; 3. open A20 in al, 0x92 or al, 00000010b out 0x92, al ; 4. enter protect mode mov eax, cr0 or eax, 0x01 mov cr0, eax ; 5. load TSS mov ax, TSSSelector ltr ax ; 6. jump to 32 bits code ; jmp dword Code32Selector : 0 ; retf 降特权级 push Stack32USelector ;指定对应特权级的栈基地址 push TopOfStack32U ;指定对应特权级的栈顶地址 push Code32Selector ;指定对应特权级代码段 push 0 retf ;降特权级执行 ; esi --> code segment label ; edi --> descriptor label InitDescItem: push eax mov eax, 0 mov ax, cs shl eax, 4 add eax, esi mov word [edi + 2], ax shr eax, 16 mov byte [edi + 4], al mov byte [edi + 7], ah pop eax ret ;模拟用户态程序 特权级3 [section .s32] [bits 32] CODE32_SEGMENT: mov ax, VideoSelector mov gs, ax mov ax, Stack32USelector mov ss, ax ;用户态 3特权级 栈信息 mov eax, TopOfStack32U mov esp, eax mov ax, Data32Selector mov ds, ax mov ebp, DTOS_OFFSET mov dh, 12 mov dl, 33 call Printf ;软中断 模拟系统调用 打印字符串 call InitDevInt ;软中断 模拟系统调用 初始化外部设备 call EnableTimer ;外部中断 模拟系统调用 放行外部的时钟中断 jmp $ ;外部设备中断初始化 软中断模拟系统调用 ; InitDevInt: push ax mov ax, 0 ; 0x80中断设计,模拟系统调? int 0x80 sti ;打开中断屏蔽总开关 pop ax ret ;打印字符串函数 软中断模拟系统调用 ; ds:ebp --> string address ; dx --> dh : row, dl : col Printf: push ax push bx ; 0x80中断设计,模拟系统调用 mov ax, 1 ;字符串打印功能 mov bx, 0x0C int 0x80 pop bx pop ax ret ; 放行外部的时钟中断 软中断模拟系统调用 ; EnableTimer: push ax mov ax, 2 int 0x80 pop ax ret Code32SegLen equ $ - CODE32_SEGMENT ;模拟内核代码段 特权级0 代码段 [section .knl] [bits 32] ;32位内核代码段 KERNEL32_SEGMENT: ; ; DefaultHandlerFunc: iret DefaultHandler equ DefaultHandlerFunc - $$ ;软中断 中断处理函数, 模拟系统调用 ; Int0x80HandlerFunc: ax0: cmp ax, 0 ; 外部设备中断初始化 jnz ax1 call InitDevIntFunc iret ax1: cmp ax, 1 ;打印字符串功能 jnz ax2 ;如果不是 跳转到 ax2 call PrintString iret ax2: cmp ax, 2 ; 放行外部的时钟中断 jnz ax3 call EnableTimerFunc iret ax3: iret Int0x80Handler equ Int0x80HandlerFunc - $$ ;时钟中断函数 ; TimerHandlerFunc: push ax push dx mov ax, [gs:((80 * 14 + 36) * 2)] cmp al, '9' je throtate inc al jmp thshow throtate: mov al, '0' thshow: mov [gs:((80 * 14 + 36) * 2)], ax mov dx, MASTER_OCW2_PORT call WriteEOI pop dx pop ax iret TimerHandler equ TimerHandlerFunc - $$ ;延时函数 ; Delay: %rep 5 nop %endrep ret ;初始化8259A ; Init8259A: push ax ; master ; ICW1 mov al, 00010001B out MASTER_ICW1_PORT, al call Delay ; ICW2 mov al, 0x20 out MASTER_ICW2_PORT, al call Delay ; ICW3 mov al, 00000100B out MASTER_ICW3_PORT, al call Delay ; ICW4 mov al, 00010001B out MASTER_ICW4_PORT, al call Delay ; slave ; ICW1 mov al, 00010001B out SLAVE_ICW1_PORT, al call Delay ; ICW2 mov al, 0x28 out SLAVE_ICW2_PORT, al call Delay ; ICW3 mov al, 00000010B out SLAVE_ICW3_PORT, al call Delay ; ICW4 mov al, 00000001B out SLAVE_ICW4_PORT, al call Delay pop ax ret ; al --> IMR register value 写中断屏蔽寄存器 ; dx --> 8259A port WriteIMR: out dx, al call Delay ret ; dx --> 8259A 读中断屏蔽寄存器 ; return: ; ax --> IMR register value ReadIMR: in ax, dx call Delay ret ; ; dx --> 8259A port 手动结束中断 WriteEOI: push ax mov al, 0x20 out dx, al call Delay pop ax ret ;打开 主8259A 对应引脚中断屏蔽 即打开中断分开关 ; EnableTimerFunc: push ax push dx mov ah, 0x0C mov al, '0' mov [gs:((80 * 14 + 36) * 2)], ax mov dx, MASTER_IMR_PORT call ReadIMR and ax, 0xFE call WriteIMR pop dx pop ax ret ; 外部设备中断初始化 ; InitDevIntFunc: push ax push dx ;初始化8259A call Init8259A ;设置8259A 屏蔽主8259A所有外部设备的中断 mov ax, 0xFF mov dx, MASTER_IMR_PORT call WriteIMR ;设置8259A 屏蔽从8259A所有外部设备的中断 mov ax, 0xFF mov dx, SLAVE_IMR_PORT call WriteIMR pop dx pop ax ret ; ds:ebp --> string address ; bx --> attribute ; dx --> dh : row, dl : col PrintString: push ebp push eax push edi push cx push dx print: mov cl, [ds:ebp] cmp cl, 0 je end mov eax, 80 mul dh add al, dl shl eax, 1 mov edi, eax mov ah, bl mov al, cl mov [gs:edi], ax inc ebp inc dl jmp print end: pop dx pop cx pop edi pop eax pop ebp ret Kernel32SegLen equ $ - KERNEL32_SEGMENT ;内核代码段长度 ;特权级3 栈段 [section .gsu] [bits 32] STACK32U_SEGMENT: times 1024 * 4 db 0 Stack32USegLen equ $ - STACK32U_SEGMENT ;栈长 TopOfStack32U equ Stack32USegLen - 1 ;栈顶 ;特权级0 栈段 [section .gsk] [bits 32] STACK32K_SEGMENT: times 1024 * 4 db 0 Stack32KSegLen equ $ - STACK32K_SEGMENT ;栈长 TopOfStack32K equ Stack32KSegLen - 1 ;栈顶
这篇关于X86系统中断处理与特权级转移 软中断实现系统调用 用户态程序使用软中断扎内核调用内核态程序的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南