When I use call intruction to swithc to a task, it will reset Bochs.
I don't know why. By the way,I put my code above 0xf0100020 in linear address, actully the phyical address is above 0x100020. Following is my code:
Compile by NASM
Code: Select all
[bits 32]
%define RELOC(x) ((x) - 0xf0000000)
jmp start
GDT:
NULL_SEL EQU $-GDT ; null descriptor is required
;(64bit per entry)
DD 0x0
DD 0x0
CODESEL EQU $-GDT ; 4GB Flat Code at 0x0 with
;max 0xFFFFF limit
DW 0xFFFF ; Limit(15-0 bit):0xFFFF
DW 0x0 ; Base(15-0 bit)
DB 0x0 ; Base(23-16 bit)
DB 0x9A ; Type:
DB 0xCF ; Limit| Flags
DB 0x10 ; Base(31-24 bit)
DATASEL EQU $-GDT ; 4GB Flat Data at 0x0 with
;max 0xFFFFF limit
DW 0xFFFF ; Limit(15-0 bit):0xFFFF
DW 0x0 ; Base(15-0 bit)
DB 0x0 ; Base(23-16 bit)
DB 0x92 ; Type:
DB 0xCF ; Limit(19-16 bit):0xF | Flags
DB 0x10 ; Base(31-24 bit)
SYS_TSS equ $-GDT ; system TSS
gdt6: dw 103
dw 0 ; set to stss
db 0
db 0x89 ; present, ring 0, 32-bit
db 0
db 0
USER_TSS equ $-GDT
gdt7: dw 103 ; user TSS
dw 0 ; set to utss
db 0
db 0x89 ; present, ring 0, 32-bit
db 0
db 0
GDT_END:
GDTR:
GDTsize DW GDT_END-GDT-1 ;limit of GDT
DD RELOC(GDT) ;address mygdt
; task state segments
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
stss: dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
dd 0, 0, 0 ; CR3, EIP, EFLAGS
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
dd 0, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw DATASEL, 0 ; ES, reserved
dw CODESEL, 0 ; CS, reserved
dw DATASEL, 0 ; SS, reserved
dw DATASEL, 0 ; DS, reserved
dw DATASEL, 0 ; FS, reserved
dw DATASEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm.bitmap
utss: dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
dd 0 ; CR3
utss_eip:
dd 0, 0 ; EIP, EFLAGS
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
utss_esp:
dd 0, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw DATASEL, 0 ; ES, reserved
dw CODESEL, 0 ; CS, reserved
dw DATASEL, 0 ; SS, reserved
dw DATASEL, 0 ; DS, reserved
dw DATASEL, 0 ; FS, reserved
dw DATASEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
end:
[global start]
start:
lgdt [RELOC(GDTR)] ; load descriptor
jmp 0x8:chen
chen:
mov ax,DATASEL ; set up data segment
mov ds,ax ;
mov es,ax ;
mov fs,ax ;
mov gs,ax ;
mov ss,ax
mov ebp,0x0
mov esp,0xf000ffff
lea eax,[ds:stss] ; set SYS_TSS
mov [ds:gdt6 + 2],ax
shr eax,16
mov [ds:gdt6 + 4],al
mov [ds:gdt6 + 7],ah
lea eax,[ds:utss] ; set USER_TSS
mov [ds:gdt7 + 2],ax
shr eax,16
mov [ds:gdt7 + 4],al
mov [ds:gdt7 + 7],ah
; initialize user TSS
lea eax,[ds:user] ; task entry point
mov [ds:utss_eip],eax
mov [ds:utss_esp],esp
; *** NOTE! ***
; ltr in real mode causes an illegal instruction interrupt
;
mov ax,SYS_TSS
ltr ax
; call user task
call USER_TSS:0
; print ending msg
call vedio3
END:
jmp END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; user task
user:
mov byte [ds:0xf00b8002],'X'
mov byte [ds:0xf00b8003],0x07
; the task switch set the NT bit, so iret does a return-from-;task
iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; character-output video routine
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
vedio3:
mov byte [ds:0xf00b8003],'C'
mov byte [ds:0xf00b8004],0x07
ret
Hope someone could give me some suggestion. Thanks in advance.