gjl606 发表于 2007-08-11 10:33

我写了切换任务的程序,但运行错误,请大家帮忙看看。

%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

gjl606 发表于 2007-08-11 10:34

dt.inc是常量和描述符宏的定义

这是用NASM写的,编译成COM文件,在虚拟DOS下运行

我觉得问题好像出在TSS和TSS2的定义上面,但我又看不出错误

mik 发表于 2007-08-12 13:50

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]
查看完整版本: 我写了切换任务的程序,但运行错误,请大家帮忙看看。