-
-
[求助]TSS异常
-
发表于: 2011-1-16 20:41 5072
-
已经从ring0进入ring3
当ring3返回ring0报TSS异常,也就是当用调用门时:
call gate:offset时tss异常了
代码如下:
%include "com.inc"
%include "os.inc"
;entry start
start:
jmp dword BOOTSEG:go
go:
mov ax,cs
mov ds,ax
mov ss,ax
mov sp,0x800
load_system:
mov dx,0x0000 ;DH-磁头号 DL-驱动器号
mov cx,0x0002 ;CH-10位磁道号低八位 CL-位7、6是磁道号高两位,位0-5为起始扇区号
mov ax,SYSSEG ;ES:BX-读入缓冲区位置(0x1000:0x0000)
mov es,ax ;AH-读扇区功能号 AL-需读的扇区数
xor bx,bx
mov ax,0x200+SYSLEN
int 0x13
jnc ok_load
die:
jmp die
ok_load:
cli ; no interrupts allowed !
mov ax, SYSSEG
mov ds, ax
xor ax, ax
mov es, ax
mov cx, 0x2000
sub si,si
sub di,di
rep movsb ;复制ds:[si](0x1000:0即0x10000)到es:[di](0:0),共cx字节
mov ax, BOOTSEG
mov ds, ax
lidt [idt_48] ; load idt with 0,0
lgdt [gdt_48] ; load gdt with whatever appropriate
; absolute address 0x00000, in 32-bit protected mode.
mov ax,0x0001 ; protected mode (PE) bit
lmsw ax ; This is it!
;mov ax,Seclector_Ds
;mov ds,ax
;mov es,ax
;mov fs,ax
;mov gs,ax
;mov ss,ax
jmp dword Selector_Cs:cs_start;+0x7c00
;jmp 0x8:cs_start+0x7c00
cs_start:
;jmp ring3
; Load TSS
mov ax,Selectot_LDT
lldt ax
mov ax, SelectorTSS
ltr ax ; 在任务内发生特权级变换时要切换堆栈,而内层堆栈的指针存放在当前任务的TSS中,所以要设置任务状态段寄存器 TR。
push Selector_Stack3
push TopOfStack3
push Selector_Ring3
push 0
retf ; Ring0 -> Ring3
ring3_start:
;db 0x66,0xB8,0x37,0x01,0x9A,0x00,0x00,0x00,0x00,0x43,0x00
mov ax,0x137 ;测试代码
;call Selector_Ring0:0
call Selector_Gate:0 ;Ring3 -> Ring0 此句异常
idt_48:
dw 0 ; idt limit=0
dw 0,0 ; idt base=0L
gdt_48: ;since we are in 0 start address,so no ds:
dw GDT_Len-1
dd 0x7c00+LGDT
LGDT:
Descriptor 0,0,0
LCs:
;Descriptor Ring3_Base,Ring3_Len,DA_CR;+DA_32
;Descriptor 0,0xfffff,DA_CR;+DA_32
;Descriptor Ring3_Base,Ring3_Len-1,DA_CR;+DA_32
Descriptor Cs_Base,Cs_Len-1,DA_CR
LDs:
Descriptor 0,0xfffff,DA_DRW
LRing3:
Descriptor Ring3_Base,Ring3_Len-1,DA_CR+DA_DPL3 ;+DA_32
LRing0:
Descriptor Ring0_Base,Ring0_Len-1,DA_CR+DA_32+DA_DPL0
LStack:
Descriptor Stack_Base,TopOfStack,DA_DRWA + DA_32; Stack, 32 位
LStack3:
Descriptor Stack_Base3,TopOfStack3, DA_DRWA + DA_32 + DA_DPL3; Stack, 32 位
LTSS:
Descriptor 0,TSSLen - 1,DA_386TSS; TSS
LGate:
Gate Selector_Ring0, 0, 0, DA_386CGate + DA_DPL3
LDT:
Descriptor LDT_Base, LDTLen - 1, DA_LDT;+ DA_DPL3 ; LDT
GDT_Len equ $-LGDT
Selector_Ds equ LDs-LGDT
Selector_Ring3 equ LRing3-LGDT+SA_RPL3
Selector_Ring0 equ LRing0-LGDT+SA_RPL0
Selector_Cs equ LCs-LGDT
Selector_Stack equ LStack - LGDT
Selector_Stack3 equ LStack3 - LGDT + SA_RPL3
SelectorTSS equ LTSS - LGDT
Selector_Gate equ LGate - LGDT + SA_RPL3
Selectot_LDT equ LDT-LGDT
Ring3_Len equ bios_flag-ring3_start+2
Ring0_Len equ 4*512
Ring0_Base equ 0
Ring3_Base equ 0x7c00+ring3_start-start
;Cs_Base equ Ring3_Base
;Cs_Len equ Ring3_Len
Cs_Base equ 0x7c00
Cs_Len equ 512
Stack_Base equ 0x7c00+LABEL_STACK-start
Stack_Base3 equ 0x7c00+LABEL_STACK3-start
LDT_Base equ 0x7c00+LLDT-start
; 全局堆栈段
LABEL_STACK:
times 88 db 0
TopOfStack equ $ - LABEL_STACK - 1
;Ring3 stack
LABEL_STACK3:
times 88 db 0
TopOfStack3 equ $ - LABEL_STACK3 - 1
; LDT
LLDT:
; 段基址 段界限 , 属性
LLDT_Code:
Descriptor Ring3_Base, Ring3_Len-1 , DA_C + DA_32 ; Code, 32 位
LDTLen equ $ - LLDT
; LDT 选择子
Selector_LDTCode equ LLDT_Code - LLDT + SA_TIL
; END of [SECTION .ldt]
LABEL_TSS:
DD 0 ; Back
DD TopOfStack ; 0 级堆栈
DD Selector_Stack ;
DD 0 ; 1 级堆栈
DD 0 ;
DD 0 ; 2 级堆栈
DD 0 ;
DD 0 ; CR3
DD 0 ; EIP
DD 0 ; EFLAGS
DD 0 ; EAX
DD 0 ; ECX
DD 0 ; EDX
DD 0 ; EBX
DD 0 ; ESP
DD 0 ; EBP
DD 0 ; ESI
DD 0 ; EDI
DD 0 ; ES
DD 0 ; CS
DD 0 ; SS
DD 0 ; DS
DD 0 ; FS
DD 0 ; GS
DD 0 ; LDT
DW 0 ; 调试陷阱标志
DW $ - LABEL_TSS + 2 ; I/O位图基址
DB 0ffh ; I/O位图结束标志
TSSLen equ $ - LABEL_TSS
times (510-($-start)) db 0
bios_flag:
db 0x55,0xaa
调得头昏眼花,还是不能进入ring0
错误如下
(0).[26264713] [0x00007c74] 001b:00000003 (unk. ctxt): call far 0043:0000 ; 9a00004300
CPU 0: Exception 0x0a - (#TS) invalid TSS occured (error_code=0x0000)
CPU 0: Interrupt 0x0a occured (error_code=0x0000)
CPU 0: Exception 0x0d - (#GP) general protection fault occured (error_code=0x0052)
CPU 0: Exception 0x08 - (#DF) double fault occured (error_code=0x0000)
CPU 0: Interrupt 0x08 occured (error_code=0x0000)
CPU 0: Exception 0x0d - (#GP) general protection fault occured (error_code=0x0042)
有没有兄弟姐妹能解决的,感激不尽!
头文件
BOOTSEG equ 0x07c0
SYSSEG equ 0x1000 ; system loaded at 0x10000 (65536).
SYSLEN equ 4 ; sectors occupied.
;----------------------------------------------------------------------------
; 描述符类型值说明
; 其中:
; DA_ : Descriptor Attribute
; D : 数据段
; C : 代码段
; S : 系统段
; R : 只读
; RW : 读写
; A : 已访问
; 其它 : 可按照字面意思理解
;----------------------------------------------------------------------------
DA_32 EQU 4000h ; 32 位段
DA_DPL0 EQU 00h ; DPL = 0
DA_DPL1 EQU 20h ; DPL = 1
DA_DPL2 EQU 40h ; DPL = 2
DA_DPL3 EQU 60h ; DPL = 3
;----------------------------------------------------------------------------
; 存储段描述符类型值说明
;----------------------------------------------------------------------------
DA_DR EQU 90h ; 存在的只读数据段类型值
DA_DRW EQU 92h ; 存在的可读写数据段属性值
DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值
DA_C EQU 98h ; 存在的只执行代码段属性值
DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值
DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
; 系统段描述符类型值说明
;----------------------------------------------------------------------------
DA_LDT EQU 82h ; 局部描述符表段类型值
DA_TaskGate EQU 85h ; 任务门类型值
DA_386TSS EQU 89h ; 可用 386 任务状态段类型值
DA_386CGate EQU 8Ch ; 386 调用门类型值
DA_386IGate EQU 8Eh ; 386 中断门类型值
DA_386TGate EQU 8Fh ; 386 陷阱门类型值
;----------------------------------------------------------------------------
; 选择子图示:
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
; ┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
; ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
; ┃ 描述符索引 ┃ TI ┃ RPL ┃
; ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
;
; RPL(Requested Privilege Level): 请求特权级,用于特权检查。
;
; TI(Table Indicator): 引用描述符表指示位
; TI=0 指示从全局描述符表GDT中读取描述符;
; TI=1 指示从局部描述符表LDT中读取描述符。
;
;----------------------------------------------------------------------------
; 选择子类型值说明
; 其中:
; SA_ : Selector Attribute
SA_RPL0 EQU 0 ; ┓
SA_RPL1 EQU 1 ; ┣ RPL
SA_RPL2 EQU 2 ; ┃
SA_RPL3 EQU 3 ; ┛
SA_TIG EQU 0 ; ┓TI
SA_TIL EQU 4 ; ┛
;----------------------------------------------------------------------------
DA_4G EQU 0xC0;0x80
; 宏 ------------------------------------------------------------------------------------------------------
;
; 描述符
; 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 & 0FFFFh ; 段界限 1 (2 字节)
dw %1 & 0FFFFh ; 段基址 1 (2 字节)
db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
%endmacro ; 共 8 字节
;
; 门
; usage: Gate Selector, Offset, DCount, Attr
; Selector: dw
; Offset: dd
; DCount: db
; Attr: db
%macro Gate 4
dw (%2 & 0FFFFh) ; 偏移 1 (2 字节)
dw %1 ; 选择子 (2 字节)
dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节)
dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节)
%endmacro ; 共 8 字节
;
%macro Set_Base_Address 2
mov eax, %1
mov word [%2+2], ax
shr eax, 16
mov byte [%2 + 3], al
mov byte [%2 + 7], ah
%endmacro
当ring3返回ring0报TSS异常,也就是当用调用门时:
call gate:offset时tss异常了
代码如下:
%include "com.inc"
%include "os.inc"
;entry start
start:
jmp dword BOOTSEG:go
go:
mov ax,cs
mov ds,ax
mov ss,ax
mov sp,0x800
load_system:
mov dx,0x0000 ;DH-磁头号 DL-驱动器号
mov cx,0x0002 ;CH-10位磁道号低八位 CL-位7、6是磁道号高两位,位0-5为起始扇区号
mov ax,SYSSEG ;ES:BX-读入缓冲区位置(0x1000:0x0000)
mov es,ax ;AH-读扇区功能号 AL-需读的扇区数
xor bx,bx
mov ax,0x200+SYSLEN
int 0x13
jnc ok_load
die:
jmp die
ok_load:
cli ; no interrupts allowed !
mov ax, SYSSEG
mov ds, ax
xor ax, ax
mov es, ax
mov cx, 0x2000
sub si,si
sub di,di
rep movsb ;复制ds:[si](0x1000:0即0x10000)到es:[di](0:0),共cx字节
mov ax, BOOTSEG
mov ds, ax
lidt [idt_48] ; load idt with 0,0
lgdt [gdt_48] ; load gdt with whatever appropriate
; absolute address 0x00000, in 32-bit protected mode.
mov ax,0x0001 ; protected mode (PE) bit
lmsw ax ; This is it!
;mov ax,Seclector_Ds
;mov ds,ax
;mov es,ax
;mov fs,ax
;mov gs,ax
;mov ss,ax
jmp dword Selector_Cs:cs_start;+0x7c00
;jmp 0x8:cs_start+0x7c00
cs_start:
;jmp ring3
; Load TSS
mov ax,Selectot_LDT
lldt ax
mov ax, SelectorTSS
ltr ax ; 在任务内发生特权级变换时要切换堆栈,而内层堆栈的指针存放在当前任务的TSS中,所以要设置任务状态段寄存器 TR。
push Selector_Stack3
push TopOfStack3
push Selector_Ring3
push 0
retf ; Ring0 -> Ring3
ring3_start:
;db 0x66,0xB8,0x37,0x01,0x9A,0x00,0x00,0x00,0x00,0x43,0x00
mov ax,0x137 ;测试代码
;call Selector_Ring0:0
call Selector_Gate:0 ;Ring3 -> Ring0 此句异常
idt_48:
dw 0 ; idt limit=0
dw 0,0 ; idt base=0L
gdt_48: ;since we are in 0 start address,so no ds:
dw GDT_Len-1
dd 0x7c00+LGDT
LGDT:
Descriptor 0,0,0
LCs:
;Descriptor Ring3_Base,Ring3_Len,DA_CR;+DA_32
;Descriptor 0,0xfffff,DA_CR;+DA_32
;Descriptor Ring3_Base,Ring3_Len-1,DA_CR;+DA_32
Descriptor Cs_Base,Cs_Len-1,DA_CR
LDs:
Descriptor 0,0xfffff,DA_DRW
LRing3:
Descriptor Ring3_Base,Ring3_Len-1,DA_CR+DA_DPL3 ;+DA_32
LRing0:
Descriptor Ring0_Base,Ring0_Len-1,DA_CR+DA_32+DA_DPL0
LStack:
Descriptor Stack_Base,TopOfStack,DA_DRWA + DA_32; Stack, 32 位
LStack3:
Descriptor Stack_Base3,TopOfStack3, DA_DRWA + DA_32 + DA_DPL3; Stack, 32 位
LTSS:
Descriptor 0,TSSLen - 1,DA_386TSS; TSS
LGate:
Gate Selector_Ring0, 0, 0, DA_386CGate + DA_DPL3
LDT:
Descriptor LDT_Base, LDTLen - 1, DA_LDT;+ DA_DPL3 ; LDT
GDT_Len equ $-LGDT
Selector_Ds equ LDs-LGDT
Selector_Ring3 equ LRing3-LGDT+SA_RPL3
Selector_Ring0 equ LRing0-LGDT+SA_RPL0
Selector_Cs equ LCs-LGDT
Selector_Stack equ LStack - LGDT
Selector_Stack3 equ LStack3 - LGDT + SA_RPL3
SelectorTSS equ LTSS - LGDT
Selector_Gate equ LGate - LGDT + SA_RPL3
Selectot_LDT equ LDT-LGDT
Ring3_Len equ bios_flag-ring3_start+2
Ring0_Len equ 4*512
Ring0_Base equ 0
Ring3_Base equ 0x7c00+ring3_start-start
;Cs_Base equ Ring3_Base
;Cs_Len equ Ring3_Len
Cs_Base equ 0x7c00
Cs_Len equ 512
Stack_Base equ 0x7c00+LABEL_STACK-start
Stack_Base3 equ 0x7c00+LABEL_STACK3-start
LDT_Base equ 0x7c00+LLDT-start
; 全局堆栈段
LABEL_STACK:
times 88 db 0
TopOfStack equ $ - LABEL_STACK - 1
;Ring3 stack
LABEL_STACK3:
times 88 db 0
TopOfStack3 equ $ - LABEL_STACK3 - 1
; LDT
LLDT:
; 段基址 段界限 , 属性
LLDT_Code:
Descriptor Ring3_Base, Ring3_Len-1 , DA_C + DA_32 ; Code, 32 位
LDTLen equ $ - LLDT
; LDT 选择子
Selector_LDTCode equ LLDT_Code - LLDT + SA_TIL
; END of [SECTION .ldt]
LABEL_TSS:
DD 0 ; Back
DD TopOfStack ; 0 级堆栈
DD Selector_Stack ;
DD 0 ; 1 级堆栈
DD 0 ;
DD 0 ; 2 级堆栈
DD 0 ;
DD 0 ; CR3
DD 0 ; EIP
DD 0 ; EFLAGS
DD 0 ; EAX
DD 0 ; ECX
DD 0 ; EDX
DD 0 ; EBX
DD 0 ; ESP
DD 0 ; EBP
DD 0 ; ESI
DD 0 ; EDI
DD 0 ; ES
DD 0 ; CS
DD 0 ; SS
DD 0 ; DS
DD 0 ; FS
DD 0 ; GS
DD 0 ; LDT
DW 0 ; 调试陷阱标志
DW $ - LABEL_TSS + 2 ; I/O位图基址
DB 0ffh ; I/O位图结束标志
TSSLen equ $ - LABEL_TSS
times (510-($-start)) db 0
bios_flag:
db 0x55,0xaa
调得头昏眼花,还是不能进入ring0
错误如下
(0).[26264713] [0x00007c74] 001b:00000003 (unk. ctxt): call far 0043:0000 ; 9a00004300
CPU 0: Exception 0x0a - (#TS) invalid TSS occured (error_code=0x0000)
CPU 0: Interrupt 0x0a occured (error_code=0x0000)
CPU 0: Exception 0x0d - (#GP) general protection fault occured (error_code=0x0052)
CPU 0: Exception 0x08 - (#DF) double fault occured (error_code=0x0000)
CPU 0: Interrupt 0x08 occured (error_code=0x0000)
CPU 0: Exception 0x0d - (#GP) general protection fault occured (error_code=0x0042)
有没有兄弟姐妹能解决的,感激不尽!
头文件
BOOTSEG equ 0x07c0
SYSSEG equ 0x1000 ; system loaded at 0x10000 (65536).
SYSLEN equ 4 ; sectors occupied.
;----------------------------------------------------------------------------
; 描述符类型值说明
; 其中:
; DA_ : Descriptor Attribute
; D : 数据段
; C : 代码段
; S : 系统段
; R : 只读
; RW : 读写
; A : 已访问
; 其它 : 可按照字面意思理解
;----------------------------------------------------------------------------
DA_32 EQU 4000h ; 32 位段
DA_DPL0 EQU 00h ; DPL = 0
DA_DPL1 EQU 20h ; DPL = 1
DA_DPL2 EQU 40h ; DPL = 2
DA_DPL3 EQU 60h ; DPL = 3
;----------------------------------------------------------------------------
; 存储段描述符类型值说明
;----------------------------------------------------------------------------
DA_DR EQU 90h ; 存在的只读数据段类型值
DA_DRW EQU 92h ; 存在的可读写数据段属性值
DA_DRWA EQU 93h ; 存在的已访问可读写数据段类型值
DA_C EQU 98h ; 存在的只执行代码段属性值
DA_CR EQU 9Ah ; 存在的可执行可读代码段属性值
DA_CCO EQU 9Ch ; 存在的只执行一致代码段属性值
DA_CCOR EQU 9Eh ; 存在的可执行可读一致代码段属性值
;----------------------------------------------------------------------------
; 系统段描述符类型值说明
;----------------------------------------------------------------------------
DA_LDT EQU 82h ; 局部描述符表段类型值
DA_TaskGate EQU 85h ; 任务门类型值
DA_386TSS EQU 89h ; 可用 386 任务状态段类型值
DA_386CGate EQU 8Ch ; 386 调用门类型值
DA_386IGate EQU 8Eh ; 386 中断门类型值
DA_386TGate EQU 8Fh ; 386 陷阱门类型值
;----------------------------------------------------------------------------
; 选择子图示:
; ┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓
; ┃ 15 ┃ 14 ┃ 13 ┃ 12 ┃ 11 ┃ 10 ┃ 9 ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0 ┃
; ┣━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━╋━━╋━━┻━━┫
; ┃ 描述符索引 ┃ TI ┃ RPL ┃
; ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━┻━━━━━┛
;
; RPL(Requested Privilege Level): 请求特权级,用于特权检查。
;
; TI(Table Indicator): 引用描述符表指示位
; TI=0 指示从全局描述符表GDT中读取描述符;
; TI=1 指示从局部描述符表LDT中读取描述符。
;
;----------------------------------------------------------------------------
; 选择子类型值说明
; 其中:
; SA_ : Selector Attribute
SA_RPL0 EQU 0 ; ┓
SA_RPL1 EQU 1 ; ┣ RPL
SA_RPL2 EQU 2 ; ┃
SA_RPL3 EQU 3 ; ┛
SA_TIG EQU 0 ; ┓TI
SA_TIL EQU 4 ; ┛
;----------------------------------------------------------------------------
DA_4G EQU 0xC0;0x80
; 宏 ------------------------------------------------------------------------------------------------------
;
; 描述符
; 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 & 0FFFFh ; 段界限 1 (2 字节)
dw %1 & 0FFFFh ; 段基址 1 (2 字节)
db (%1 >> 16) & 0FFh ; 段基址 2 (1 字节)
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2 (2 字节)
db (%1 >> 24) & 0FFh ; 段基址 3 (1 字节)
%endmacro ; 共 8 字节
;
; 门
; usage: Gate Selector, Offset, DCount, Attr
; Selector: dw
; Offset: dd
; DCount: db
; Attr: db
%macro Gate 4
dw (%2 & 0FFFFh) ; 偏移 1 (2 字节)
dw %1 ; 选择子 (2 字节)
dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (2 字节)
dw ((%2 >> 16) & 0FFFFh) ; 偏移 2 (2 字节)
%endmacro ; 共 8 字节
;
%macro Set_Base_Address 2
mov eax, %1
mov word [%2+2], ax
shr eax, 16
mov byte [%2 + 3], al
mov byte [%2 + 7], ah
%endmacro
赞赏
他的文章
- [求助]TSS异常 5073
- 个人原因删除 1223
- [注意]学写操作系统正式移往博客 916
- [分享]学写操作系统(一)……(十五) 19056
- 删除 1272
看原图
赞赏
雪币:
留言: