目的是实现两个任务tss1和tss2,tss1输出A然后死循环,当四次时钟中断到来后,切换到tss2,tss2输出B后死循环,等待四次时钟中断后切换到tss1。如此循环往复。可是用切换到tss1后,中断总是有问题,但是在跳入tss1之前,用int 0x20实验,中断时没问题的。轻大家帮忙看一下,本程序用nasm编译。tss1和tss2切换的代码_ispTimer还没来得及实验。
程序源代码:
%macro Descriptor 3 ;基址,界限,属性
DW %2
DW %1
DB %1 >> 16
DW %3 | ((%2 >> 8) & 0xF00)
DB %1 >> 24
%endmacro
%macro Gate 4 ;selector,Offset,MainAttr,DCount
DW %2
DW %1
DB (%4 & 0x1F)
DB %3
DW %2 >> 16
%endmacro
StartSeg EQU 0x7C00
;----------------------------------------------------------
;起始代码
ORG 0x0000
[BITS 16]
jmp dword 0x7c0:StartLabel ;主要目的是加载CS
StartLabel:
mov ax,cs
mov ds,ax
mov es,ax
mov ax,0x6c00
mov ss,ax
mov sp,0xFFF
;从软盘中读取接下来的8个扇区,到0x7c00 + 512后面,并执行之
;做一个任务切换的逻辑,8个扇区应该是足够了
cli
loop1:
;软盘复位
xor ax,ax
int 13h
;读取接下来的个扇区,任务1和任务2的相关数据,
;编译完成后查看文件大小,看一下扇区够不够
mov ax,0x0208
mov cx,0x0002
xor dx,dx
mov bx,512
int 13h
test ah,0xFF
jnz loop1
;初始化各个段
xor ebx,ebx
mov bx,cs
shl ebx, 4
;初始化GdtItemTss1
mov eax,TSS1Start
mov edi,GdtItemTss1
call initDescp
; 初始化 GdtItemLdt1
mov eax,_Ldt1Start
mov edi,GdtItemLdt1
call initDescp
;初始化GdtItemTss2
mov eax,TSS2Start
mov edi,GdtItemTss2
call initDescp
; 初始化 GdtItemLdt2
mov eax,_Ldt2Start
mov edi,GdtItemLdt2
call initDescp
; 初始化 GdtItemISP
mov eax,_ispStart
mov edi,GdtItemISP
call initDescp
; 初始化 Ldt1ItemCode
mov eax,_Ldt1CodeStart
mov edi,Ldt1ItemCode
call initDescp
; 初始化 Ldt1ItemStack0
mov eax,_Ldt1Stack0
mov edi,Ldt1ItemStack0
call initDescp
; 初始化 Ldt1ItemStack3
mov eax,_Ldt1Stack3
mov edi,Ldt1ItemStack3
call initDescp
; 初始化 Ldt2ItemCode
mov eax,_Ldt2CodeStart
mov edi,Ldt2ItemCode
call initDescp
; 初始化 Ldt2ItemStack0
mov eax,_Ldt2Stack0
mov edi,Ldt2ItemStack0
call initDescp
; 初始化 Ldt2ItemStack3
mov eax,_Ldt2Stack3
mov edi,Ldt2ItemStack3
call initDescp
; 初始化 GdtItemFstPm
mov eax,_FstPm
mov edi,GdtItemFstPm
call initDescp
;初始化 GdtItemTmpTSS
mov eax,_tmpTSSBegin
mov edi,GdtItemTmpTSS
call initDescp
;初始化临时堆栈GdtTmpStack0
mov eax,tmpStack0
mov edi,GdtTmpStack0
call initDescp
;初始化全局数据段GdtItemGlobalData
mov eax,_GlobalVariable
mov edi,GdtItemGlobalData
call initDescp
;GDT初始化
lgdt [GdtPtr]
;IDT初始化
lidt [IdtPtr]
;切换到保护模式
mov eax,cr0
or ax,1
mov cr0,eax
jmp GSELFSTPM:0
;----------------------
;输入:ebx:段基址,eax,偏移量,ds:edi,描述符开始地址
initDescp:
add eax,ebx
add edi,2
mov [ds:edi],ax
shr eax,16
add edi,2
mov [ds:edi],al
add edi,3
mov [ds:edi],ah
ret
;------------------------------------------------
;下面是GDT
GdtStart:
Descriptor 0 , 0 , 0
GdtItemTss1:
Descriptor 0 , ( TSS1LEN - 1 ) , 0x89