0

我正在学习 IA-32 任务切换,这是我的代码:

%include    "pm.inc"      ;this code is loaded on 0x100000
section .text
start:
bits 32
mov ax,10h
mov ds,ax
mov ss,ax
mov esp,systemStack
mov eax,100000h
add eax,tss0
mov [tss0Segment+2],ax
shr eax,16
mov [tss0Segment+4],al
mov [tss0Segment+7],ah
mov eax,100000h
add eax,tss1
mov [tss1Segment+2],ax
shr eax,16
mov [tss1Segment+4],al
mov [tss1Segment+7],ah
mov eax,100000h
add eax,ldt0
mov [ldt0Segment+2],ax
shr eax,16
mov [ldt0Segment+4],al
mov [ldt0Segment+7],ah
mov eax,100000h
add eax,ldt1
mov [ldt1Segment+2],ax
shr eax,16
mov [ldt1Segment+4],al
mov [ldt1Segment+7],ah        ;initialize some descriptor
lgdt [gdtPtr]
lidt [idtPtr]
jmp 8:next
next:
setIdt:
mov ebx,80*8+idt
mov word [ebx+2],codeSegment-gdt
mov eax,putchar
mov word [ebx],ax
shr eax,16
mov word [ebx+6],ax
mov al,byte [ebx+5]
add al,01100000b
mov byte [ebx+5],al


ring3:
mov ax,tss0Segment-gdt
ltr ax
mov ax,ldt0Segment-gdt
lldt ax
push ldt0data-ldt0+7
push systemStack
push ldt0code-ldt0+7
push task0
retf





putchar:                ;this function is used for print letters on the screen
push bx
mov dx,3d4h
mov al,0eh
out dx,al
mov dx,3d5h
in al,dx
mov ah,al
mov dx,3d4h
mov al,0fh
out dx,al
mov dx,3d5h
in al,dx
cmp cl,0dh
jne .s1
cmp ax,0
jne .next
inc ax
.next:
mov bl,80
div bl
inc ax
mul bl
jmp setCursor
.s1:
cmp cl,0ah
jne .putchar
add ax,80
jmp roll
.putchar:
mov bx,videoSegment-gdt
mov es,bx
shl ax,1
mov bx,ax
mov [es:bx],cl
shr ax,1
inc ax
roll:
cmp ax,2000
jl setCursor
mov bx,videoSegment-gdt
mov es,bx
mov si,0a0h
mov di,0h
mov ecx,1920
.s:
mov eax,[es:si]
mov [es:di],eax
add si,2
add di,2
loop .s
mov bx,3840
mov cx,80
.cls:
mov word [es:bx],720h
add bx,2
loop .cls
mov ax,1920
setCursor:
mov bx,ax
mov dx,3d4h
mov al,0eh
out dx,al
mov dx,3d5h
mov al,bh
out dx,al
mov dx,3d4h
mov al,0fh
out dx,al
mov dx,3d5h
mov al,bl
out dx,al
pop bx
iret
cls:
push bx
mov ax,videoSegment-gdt
mov es,ax
mov ecx,80*25
mov bx,0
.s:
mov byte [es:bx],0h
add bx,2
loop .s
mov ax,0
jmp setCursor
section .data 
align 8
gdt:            Descriptor       0,         0, 0
codeSegment:    Descriptor       100000h,           0ffffh, DA_C + DA_32
dataSegment:    Descriptor       100000h,           0ffffh,DA_DRW    
videoSegment:   Descriptor      0b8000h,            0ffffh, DA_DRW 
tss0Segment:    Descriptor     0,           103, DA_386TSS+DA_DPL3  
tss1Segment:    Descriptor     0,           103, DA_386TSS+DA_DPL3  
ldt0Segment:    Descriptor     0,           67, DA_LDT
ldt1Segment:    Descriptor     0,           67, DA_LDT
gdtLen      equ $ - gdt
times  128 dd 0
systemStack:
gdtPtr  dw gdtLen-1
    dd gdt+100000h
align 8
idt:
%rep 80
Gate 0,0,0,0
%endrep
    Gate 8,0,0,DA_386IGate
%rep 174
Gate 0,0,0,0
%endrep

idtLen equ $-idt
idtPtr dw idtLen-1
   dd idt+100000h
align 8

ldt0:Descriptor       0,            0, 0
ldt0code:Descriptor       100000h,          0ffffh, DA_C + DA_32+DA_DPL3
ldt0data:Descriptor       100000h,          0ffffh,DA_DRW +DA_DPL3


tss0:
dd 0,tss0Stack,10h,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,ldt0Segment-gdt,8000000h
times 128 dd 0
tss0Stack:

ldt1:Descriptor       0,            0, 0
ldt1code:Descriptor       100000h,          0ffffh, DA_C + DA_32+DA_DPL3
ldt1data:Descriptor       100000h,          0ffffh,DA_DRW +DA_DPL3


tss1:
dd 0,tss1Stack,10h,0,0,0,0,0,task1,200h,0,0,0,0,usrStack1,0,0,0,17h,0fh,17h,17h,17h,017h,ldt1Segment-    gdt,8000000h
times 128 dd 0
tss1Stack:

task0:
mov cl,'a'
int 80
jmp tss1Segment-gdt:0
jmp task0

task1:
mov cl,'b'
int 80
jmp tss0Segment-gdt:0
jmp task1
align 8
times 128 dd 0
usrStack1:

有一些关于初始化描述符和在屏幕上打印字母的代码,我没有粘贴。这里是问题:进程成功进入task0,然后跳转到task1,我认为这是成功的(我检查了tr,ldtr ss,esp改得很好)然后奇怪的事情发生了:当eip移动到命令mov cl,'b'时,bochs告诉我发生中断并且中断门无效(因为我没有设置除用于打印功能的数字 0x50 中断之外的其他 idt 编号),这是我第一次遇到由mov!我的代码有什么问题引起的中断?bug在哪里?

4

0 回答 0