;
;head.s contains the 32-bit startup code.;Two L3 task multitasking. The code of tasks are in kernel area,;just like the Linux. The kernel code is located at 0x10000.;KRN_BASE = 10000h
TSS0_SEL = 20h
LDT0_SEL = 28h
TSS1_SEL = 30h
LDT1_SEL = 38h
.386p
.model huge
ts0seg segment at 20h
ts0lab label byte
ts0seg ends
ts1seg segment at 30h
ts1lab label byte
ts1seg ends
.codestartup_32:assumeds:@codemoveax,10hmovds,eaxmoves,eaxmovfs,eaxmovgs,eaxlssesp,FWORD PTR [stack_ptr];setup base fields of descriptors.
movebx,KRN_BASEmovecx,gdtleaeax,tss0movedi,TSS0_SELcallset_baseleaeax,ldt0movedi,LDT0_SELcallset_baseleaeax,tss1movedi,TSS1_SELcallset_baseleaeax,ldt1movedi,LDT1_SELcallset_basecallsetup_idtcallsetup_gdtmov eax,10h ;reload all the segment registers
mov ds,eax ;after changing gdt.
moves,eaxmovfs,eaxmovgs,eaxlssesp,FWORD PTR [stack_ptr];设置8253定时芯片。把计数器通道0设置成每隔10毫秒向中断控制器发送一个中断请求信号;8253具有3个独立的计数通道,采用减1计数方式。;方式3为:方波发生器,最适合计算机。;setup up timer 8253 chip.
mov al,36h ;设置通道0工作在方式3
mov edx,43h ;8253芯片控制寄存器写端口
outdx,almov eax,11930 ;timer frequency 100 HZ 8253芯片的时钟输入频率是1.193180mhz
mov edx,40h ;通道0的端口
out dx,al ;分两次把初始计数值写入通道0
moval,ahoutdx,al;setup timer & system call interrupt descriptors.
moveax,00080000hmov ax,1A0h;timer_interrupt
movdx,08E00hmovecx,20hlea esi,[ecx*8+idt]mov[esi],eaxmov [esi+4],edxmov ax,1e4h;[system_interrupt]
movdx,0ef00hmovecx,080hlea esi,[ecx*8+idt]mov[esi],eaxmov [esi+4],edx;unmask the timer interrupt.
movedx,21hinal,dxandal,0fehoutdx,al;Move to user mode (task 0)
db 9ch;pushf
anddword ptr [esp],0ffffbfffh
db 9dh;popf
moveax,TSS0_SELltraxmoveax,LDT0_SELlldtaxmov dword ptr [current],0
sti
push17hpushstack0_ptr
db 9ch;pushf
push0fhpushtask0
db 0cfh;iret
setup_gdt:
lgdtfword ptr [lgdt_opcode]ret
setup_idt:
leaedx,ignore_intmoveax,00080000hmov ax,dx ;selector = 0x0008 = cs
mov dx,8E00h ;interrupt gate - dpl=0, present
leaedi,idtmov ecx,256
rp_sidt:
mov[edi],eaxmov [edi+4],edxadd edi,8
dececxjnerp_sidtlidtfword ptr [lidt_opcode]ret
;in: eax - logic addr; ebx = base addr ;;ecx - table addr; edi - descriptors offset.
set_base:
addeax,ebxaddedi,ecxmov [edi+2],axror eax,16
mov [edi+4],almov [edi+7],ahror eax,16
ret
write_char:
pushgspushebxpusheaxmovebx,18hmovgs,bxmovebx,[scr_loc]shl ebx,1assumegs:nothingmov gs:[ebx],alshr ebx,1
incebxcmp ebx,2000
jbfmov ebx,0
f: movscr_loc,ebxpopeaxpopebxpopgsret
;This is the default interrupt "handler"
align DWORDignore_int:
pushdspusheaxmoveax,10hmovds,eaxmov eax,67 ;print ‘C‘
callwrite_charpopeaxpopds
db 0cfh;iret
;Timer interrupt handler
;align dword
dw 0
timer_interrupt:
pushdspushedxpushecxpushebxpusheaxmoveax,10hmovds,eaxmoval,20hout 20h,al ;允许其他硬件中断,则向8253发送EOI命令
mov eax,1
cmpcurrent,eaxjets0mov[current],eaxjmpfar ptr ts1labjmpts2ts0: mov dword ptr [current],0 ;若当前任务是1,则把0存入current,并跳转到任务0
jmpfar ptr ts0labts2: popeaxpopebxpopecxpopedxpopds
db 0cfh;iret
;system call handler
align DWORDsystem_interrupt:
pushdspushedxpushecxpushebxpusheaxmovedx,10hmovds,edxcallwrite_charpopeaxpopebxpopecxpopedxpopds
db 0cfh;iret
current dd0scr_loc dd0align DWORD
dw0
lidt_opcode:dw256*8-1 ;idt contains 256 entries
dd idt + KRN_BASE ;This will be rewrite by code.
align DWORD
dw0
lgdt_opcode:dw (end_gdt-gdt)-1 ;so does gdt
dd gdt + KRN_BASE ;This will be rewrite by code.
align DWORD
dd0
idt:dd512 dup(0) ;idt is uninitialized
gdt:dd 00000000h;NULL descriptor
dd 00000000h
dd 000007ffh;8Mb 0x08, base = 0x10000
dd 00c09a01h
dd 000007ffh;8Mb 0x10
dd 00c09201h
dd 80000002h;screen 0x18 - for display
dd 00c0920bh
dd 00000068h;TSS0 descr 0x20
dd 0000e901h
dd 00000040h;LDT0 descr 0x28
dd 0000e201h
dd 00000068h;TSS1 descr 0x30
dd 0000e901h
dd 00000040h;LDT1 descr 0x38
dd 0000e201hend_gdt:dd128 dup(0)stack_ptr:dd stack_ptr
dw 10h
align DWORDldt0:dd 00000000h
dd 00000000h
dd 000003ffh;0x0f, base = 0x10000
dd 00c0fa01h
dd 000003ffh;0x17
dd 00c0f201htss0:dd0 ;back link
dd stack0_krn_ptr,10h ;esp0, ss0
dd 0, 0 ;esp1, ss1
dd 0, 0 ;esp2, ss2
dd 0 ;cr3
dd task0 ;eip
dd 200h ;eflags
dd 0, 0, 0, 0 ;eax, ecx, edx, ebx
dd stack0_ptr,0, 0, 0 ;esp, ebp, esi, edi
dd 17h,0fh,17h,17h,17h,17h ;es, cs, ss, ds, fs, gs
dd LDT0_SEL ;ldt
dd 8000000h ;trace bitmap
dd128 dup(0)stack0_krn_ptr:dd0align DWORD
dd0
ldt1:dd 00000000h
dd 00000000h
dd 000003ffh;0x0f, base = 0x10000
dd 00c0fa01h
dd 000003ffh;0x17
dd 00c0f201htss1:dd0 ;back link
dd stack1_krn_ptr, 10h ;esp0, ss0
dd 0, 0 ;esp1, ss1
dd 0, 0 ;esp2, ss2
dd 0 ;cr3
dd task1 ;eip
dd 200h ;eflags
dd 0, 0, 0, 0 ;eax, ecx, edx, ebx
dd stack1_ptr, 0, 0, 0 ;esp, ebp, esi, edi
dd 17h,0fh,17h,17h,17h,17h ;es, cs, ss, ds, fs, gs
dd LDT1_SEL ;ldt
dd 8000000h ;trace bitmap
dd128 dup(0)stack1_krn_ptr:dd0
task0:
moveax,17hmovds,axmov eax,65 ;print ‘A‘
int80hmovecx,0fffhs0:loop s0jmptask0
dd128 dup(0)stack0_ptr:dd0
task1:
moveax,17hmovds,axmov eax,66 ;print ‘B‘
int80hmovecx,0fffhs1:loop s1jmptask1
dd128 dup(0)stack1_ptr:dd0org 2000h-2dw0end startup_32