我写了切换任务的程序,但运行错误,请大家帮忙看看。
%include "dt.inc"org 0100h ; COM文件
jmp label_inProtectMode
; 定义描述符
null_GDT: descriptor 0,0,0 ; 空描述符
tast1GDT descriptor 0, tast1Len - 1, DA_C + DA_32
tast2GDT descriptor 0, tast2Len - 1, DA_C + DA_32
tssGDT: descriptor 0, tss_len - 1, DA_E386TSS ; TSS描述府
tss2GDT: descriptor 0, tss2_len - 1, DA_E386TSS
showGDT: descriptor 0B8000h, 0ffffh, DA_DRW ; 显存
GdtPtr dw $ - null_GDT ; GDTR界限
dd 0 ; GDTR基地址
tast1Selector equ tast1GDT - null_GDT
tast2Selector equ tast2GDT - null_GDT
tssSelector equ tssGDT - null_GDT ; TSS选择子
tss2Selector equ tss2GDT - null_GDT ; TSS2选择子
showSelector equ showGDT - null_GDT
; 任务状态段TSS
label_tss:
DW 0 ; 链接字段
DW 0
DD 0 ; 0级堆栈指针
DW 0 ; SS0
DW 0
DD 0 ; 1级堆栈指针
DW 0 ; SS1
DW 0
DD 0 ; 2级堆栈指针
DW 0 ; SS2
DW 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
DW 0 ; ES
DW 0
DW 0 ; CS
DW 0
DW 0 ; SS
DW 0
DW 0 ; DS
DW 0
DW 0 ; FS
DW 0
DW 0 ; GS
DW 0
DW 0 ; LDT
DW 0
DW 0 ; TSS的特别属性字
DW $ - label_tss + 2 ; 指向I/0许可位图区的指针
DW 0FFH ; I/0许可位图结束字节
tss_len equ $ - label_tss
; 任务状态段TSS2
label_tss2:
DW 0 ; 链接字段
DW 0
DD 0 ; 0级堆栈指针
DW 0 ; SS0
DW 0
DD 0 ; 1级堆栈指针
DW 0 ; SS1
DW 0
DD 0 ; 2级堆栈指针
DW 0 ; SS2
DW 0
DD 0 ; CR3
DD label_tast2 ; 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
DW 0 ; ES
DW 0
DW tast2Selector ; CS
DW 0
DW 0 ; SS
DW 0
DW 0 ; DS
DW 0
DW 0 ; FS
DW 0
DW 0 ; GS
DW 0
DW 0 ; LDT
DW 0
DW 0 ; TSS的特别属性字
DW $ - label_tss2 + 2 ; 指向I/0许可位图区的指针
DW 0FFH ; I/0许可位图结束字节
tss2_len equ $ - label_tss2
; 进入保护模式
label_inProtectMode:
mov ax, cs ; 初始化段寄存器
mov ds, ax
cli ; 清除EFLAGS的IF位(bit9),不响应可屏蔽中断
inal, 92h ; 打开A20地址线(bit1为1)
oral, 00000010b
out 92h, al
mov eax, cr0 ; 设置CRO的PE位(bit0)为1
oreax, 1
mov cr0, eax
xor eax, eax
mov eax, ds
shl eax, 4
add eax, null_GDT ; 初始化GDTR的基地址
mov dword , eax
lgdt ; 加载GDTR
xor eax, eax
mov eax, ds
shl eax, 4
add eax, label_tast1 ; 设置GDT中Tast1描述府的段基址
mov word , ax
shr eax, 16
mov byte , al
mov byte , ah
xor eax, eax
mov eax, ds
shl eax, 4
add eax, label_tast2 ; 设置GDT中Tast2描述府的段基址
mov word , ax
shr eax, 16
mov byte , al
mov byte , ah
xor eax, eax
mov eax, ds
shl eax, 4
add eax, label_tss ; 设置GDT中TSS描述府的段基址
mov word , ax
shr eax, 16
mov byte , al
mov byte , ah
xor eax, eax
mov eax, ds
shl eax, 4
add eax, label_tss2 ; 设置GDT中TSS2描述府的段基址
mov word , ax
shr eax, 16
mov byte , al
mov byte , ah
jmp dword tast1Selector:0 ; 调用tast1的代码
; tast1
label_tast1:
mov ax, tssSelector
ltr ax
jmp tss2Selector:0
tast1Len equ $ - label_tast1
; tast2
label_tast2:
mov ax, showSelector
mov gs, ax
mov edi, (80 * 10 + 10) * 2
mov ah, 0Ch
mov al, '2'
mov , ax
jmp $
tast2Len equ $ - label_tast2 dt.inc是常量和描述符宏的定义
这是用NASM写的,编译成COM文件,在虚拟DOS下运行
我觉得问题好像出在TSS和TSS2的定义上面,但我又看不出错误 LZ:
TSS 是一种系统 desctriptor,NASM 偶不熟悉 desctriptor 应该是个宏吧,没看你 dt.inc 是如何定义的,不知你的 TSS 定义是否正确。还要注意另一个问题:该问权限要设置得当。
偶看 LZ 的代码错误还是挺多的。
1、TSS descriptor 不是这样用法的。TSS 是由 processor 发生在任务切换时自动引用的。获取 TSS 需经由 Task Gate(任务门)或 Call Gate(调用门)来切换,因此要使用 TSS descriptor 还得建立一个 Task Gate descritptor 或 call gate descriptor。象你这样使用 far call 或 far jmp 直接转移控制是不能引用到 TSS 的。关于这方面还是挺复杂的,也不是两三语可以讲明白的。
2、你这段进入保护模式的代码也有问题,应该先设好 GDT 才转到保护模式。当进入保护模式后直接转移控制权就显得有问题了。
页:
[1]