跑步

Windows编译环境下的Linux启动代码

2019-09-13 20:10:51来源:励志吧0次阅读

过去,有许多讲Linux源代码的资料和书籍,但所讲解的代码都是要在Linux环境下编译的,这给只安装了Windows而又想一睹Linux启动代码的用户带来了极大的不便。监于此,本人将可在Windows编译环境下的编译运行的Linux启动源代码公之于众,以供大家学习、参考。

由于代码是从Linux源代码翻译过来的,且赵炯博士已经注释的十分详细,这里就不再多说了。代码为汇编语言,编译环境为TASM+TLINK。

1。bootsect.asm,这个文件是从bootsect.s翻译过来的,功能相同,我在文件末尾增加了用来调试的error例程。内容为:

code segment

;define the const here

SYSSIZE = 3000h

SETUPLEN = 4 ; nr of setup-sectors

BOOTSEG = 07c0h ; original address of boot-sector

INITSEG = 9000h ; we move boot here - out of the way

SETUPSEG = 9020h ; setup starts here

SYSSEG = 1000h ; system loaded at 0x10000 (65536).

ENDSEG = SYSSEG + SYSSIZE ; where to stop loading

assume cs:code,ds:code,es:code

start:

mov ax,BOOTSEG

mov ds,ax

mov ax,INITSEG

mov es,ax

mov cx,256

sub si,si

sub di,di

rep movsw

;jump to 0x90000

mov bx,8ff0h

mov ds,bx

mov bx,00h

mov word ptr ds:[bx],offset go

mov word ptr ds:[bx]+2,9000h

mov bx,00h

jmp dword ptr [bx]

go LABEL FAR

mov ax,INITSEG

mov ds,ax

mov es,ax

; put stack at 0x9ff00.

mov ss,ax

mov sp,0FF00h ; arbitrary value >>512

; load the setup-sectors directly after the bootblock.

; Note that 'es' is already set up.

load_setup:

;copy sector 2,3,4,5 code to 0x90200,seg=0x9020

mov dx,0000h ; drive 0, head 0

mov cx,0002h ; sector 2, track 0

mov bx,0200h ; address = 512, in INITSEG

mov ax,0200h+SETUPLEN ; service 2, nr of sectors

int 13h ; read it

jnc ok_load_setup ; ok - continue

mov dx,0000h

mov ax,0000h ; reset the diskette

int 13h

jmp load_setup

ok_load_setup:

; Get disk drive parameters, specifically nr of sectors/track

mov dl,00h

mov ax,0800h ; AH=8 is get drive parameters

int 13h

mov ch,00h

mov sectors,cx

mov ax,INITSEG

mov es,ax

; Print some inane message

mov ah,03h ; read cursor pos

xor bh,bh

int 10h

mov cx,24

mov bx,0007h ; page 0, attribute 7 (normal)

mov bp,offset msg1

mov ax,1301h ; write string, move cursor

int 10h

; ok, we've written the message, now

; we want to load the system (at 0x10000)

mov ax,SYSSEG

mov es,ax ; segment of 0x010000

call read_it

call kill_motor

; After that we check which root-device to use. If the device is

; defined (;= 0), nothing is done and the given device is used.

; Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending

; on the number of sectors that the BIOS reports currently.

mov ax,root_dev

cmp ax,00h

jne root_defined

mov bx,sectors

mov ax,0208h ; /dev/ps0 - 1.2Mb

cmp bx,15

je root_defined

mov ax,021ch ; /dev/PS0 - 1.44Mb

cmp bx,18

je root_defined

undef_root: ;will loop for ever

jmp undef_root

root_defined:

mov root_dev,ax

; after that (everyting loaded), we jump to

; the setup-routine loaded directly after

; the bootblock:

;jump to 0x90200

mov bx,8ff0h

mov ds,bx

mov bx,00h

mov word ptr ds:[bx],0000h

mov word ptr ds:[bx]+2,9020h

mov bx,00h

jmp dword ptr [bx]

; This routine loads the system at address 0x10000, making sure

; no 64kB boundaries are crossed. We try to load it as fast as

; possible, loading whole tracks whenever we can.

;

; in: es - starting address segment (normally 0x1000)

;

sread dw 1+SETUPLEN ; sectors read of current track

head dw 0 ; current head

track dw 0 ; current track

read_it:

mov ax,es

test ax,0fffh

die: jne die ; es must be at 64kB boundary

xor bx,bx ; bx is starting address within segment

mov ax,INITSEG

mov ds,ax

rp_read:

mov ax,es

cmp ax,ENDSEG ; have we loaded all yet?

jb ok1_read

ret

ok1_read:

mov ax,INITSEG

mov ds,ax

mov ax,sectors

sub ax,sread

mov cx,ax

shl cx,09h

add cx,bx

jnc ok2_read

je ok2_read

xor ax,ax

sub ax,bx

shr ax,09h

ok2_read:

call read_track

mov cx,ax

add ax,sread

cmp ax,sectors

jne ok3_read

mov ax,01h

sub ax,head

jne ok4_read

inc track

ok4_read:

mov head,ax

xor ax,ax

ok3_read:

mov sread,ax

shl cx,09h

add bx,cx

jnc rp_read

mov ax,es

add ax,1000h

mov es,ax

xor bx,bx

jmp rp_read

read_track:

push ax

push bx

push cx

push dx

mov dx,track

mov cx,sread

inc cx

mov ch,dl

mov dx,head

mov dh,dl

mov dl,00h

and dx,0100h

mov ah,02h

int 13h

jc bad_rt

pop dx

pop cx

pop bx

pop ax

ret

bad_rt:

mov ax,00h

mov dx,00h

int 13h

pop dx

pop cx

pop bx

pop ax

jmp read_track

;/*

; * This procedure turns off the floppy drive motor, so

; * that we enter the kernel in a known state, and

; * don't have to worry about it later.

; */

kill_motor:

push dx

mov dx,03f2h

mov al,0h

out dx,al

pop dx

ret

;read fail and show error,我自己加的,可以在需要的地方调用以显示信息

error:

mov ax,0b800h

mov es,ax

xor di,di

mov ax,INITSEG

mov ds,ax

mov si,offset strError

mov cx,20

repShow:

lodsb

stosb

mov al,87h

stosb

dec cx

cmp cx,0

jne repShow

ret

;define the vars here

sectors dw 00h

strError db 'ERROR***********ERROR***********'

msg1 db 13,10,'Loading system ...',13,10,13,10

; ROOT_DEV: 0x000 - same type of floppy as boot.

; 0x301 - first partition on first drive etc

ROOT_DEV dw 0

;ROOT_DEV = 0306h

code ends

end start

2。setup.asm,是从setup.s翻译过来的。但这里为16位段的386指令,且我增加了可以输出字符的代码段和数据段。内容为:

P386

jump macro selector,offset

db 0eah ;

dw offset ;

dw selector ;

endm

code segment use16

;define the const

INITSEG = 9000h ; we move boot here - out of the way

SYSSEG = 1000h ; system loaded at 0x10000 (65536).

SETUPSEG = 9020h ; this is the current segment

assume cs:code,ds:code,es:code

start:

mov ax,INITSEG ; this is done in bootsect already, but...

mov ds,ax

mov ah,03h ; read cursor pos

xor bh,bh

int 10h ; save it in known place, con_init fetches

mov ds:[0],dx ; it from 0x90000.

; Get memory size (extended mem, kB)

mov ah,88h

int 15h

mov ds:[2],ax

; Get video-card data:

mov ah,0fh

int 10h

mov ds:[4],bx ; bh = display page

mov ds:[6],ax ; al = video mode, ah = window width

; check for EGA/VGA and some config parameters

mov ah,12h

mov bl,10h

int 10h

mov ds:[8],ax

mov ds:[10],bx

mov ds:[12],cx

; Get hd0 data

mov ax,0000h

mov ds,ax

mov si,0104h ;4*41h

mov ax,INITSEG

mov es,ax

mov di,0080h

mov cx,10h

rep movsb

; Get hd1 data

mov ax,0000h

mov ds,ax

mov si,0118 ;4*46h

mov ax,INITSEG

mov es,ax

mov di,0090h

mov cx,10h

rep movsb

; Check that there IS a hd1 :-)

mov ax,01500h

mov dl,81h

int 13h

jc no_disk1

cmp ah,03h

je is_disk1

no_disk1:

mov ax,INITSEG

mov es,ax

mov di,0090h

mov cx,10h

mov ax,00h

rep stosb

is_disk1:

; now we want to move to protected mode ...

cli ; no interrupts allowed ;

; first we move the system to it's rightful place

mov ax,0000h

cld ; 'direction'=0, movs moves forward

do_move:

mov es,ax ; destination segment

add ax,1000h

cmp ax,9000h

jz end_move

mov ds,ax ; source segment

xor di,di

xor si,si

mov cx,8000h

rep movsw

jmp do_move

; then we load the segment descriptors

end_move:

mov ax,SETUPSEG ; right, forgot this at first. didn't work :-)

mov ds,ax

lidt qword ptr idt_48 ; load idt with 0,0 ;can't run in via cpu ,so mark off

lgdt qword ptr gdt_48 ; load gdt with whatever appropriate

; that was painless, now we enable A20

call empty_8042

mov al,0D1h ; command write

out 64h,al

call empty_8042

mov al,0DFh ; A20 on

out 60h,al

call empty_8042

; well, that went ok, I hope. Now we have to reprogram the interrupts :-(

; we put them right after the intel-reserved hardware interrupts, at

; int 0x20-0x2F. There they won't mess up anything. Sadly IBM really

; messed this up with the original PC, and they haven't been able to

; rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,

; which is used for the internal hardware interrupts as well. We just

; have to reprogram the 8259's, and it isn't fun.

mov al,11h ; initialization sequence

out 20h,al ; send it to 8259A-1

dw 00ebh,00ebh ; jmp $+2, jmp $+2

out 0A0h,al ; and to 8259A-2

dw 00ebh,00ebh

mov al,20h ; start of hardware int's (0x20)

out 21h,al

dw 00ebh,00ebh

mov al,28h ; start of hardware int's 2 (0x28)

out 0A1h,al

dw 00ebh,00ebh

mov al,04h ; 8259-1 is master

out 21h,al

dw 00ebh,00ebh

mov al,02h ; 8259-2 is slave

out 0A1h,al

dw 00ebh,00ebh

mov al,01h ; 8086 mode for both

out 21h,al

dw 00ebh,00ebh

out 0A1h,al

dw 00ebh,00ebh

mov al,0FFh ; mask off all interrupts for now

out 21h,al

dw 00ebh,00ebh

out 0A1h,al

; well, that certainly wasn't fun :-(. Hopefully it works, and we don't

; need no steenking BIOS anyway (except for the initial loading :-).

; The BIOS-routine wants lots of unnecessary data, and it's less

; "interesting" anyway. This is how REAL programmers do it.

;

; Well, now's the time to actually move into protected mode. To make

; things as simple as possible, we do no register set-up or anything,

; we let the gnu-compiled 32-bit programs do that. We just jump to

; absolute address 0x00000, in 32-bit protected mode.

mov eax,00000001h

mov cr0,eax

mov ax,0001h ; protected mode (PE) bit

lmsw ax ; This is it;

;jmp offset 0 of segment 8 (cs)

;mov bx,0018h ;jump segment select

;mov ds,bx

;mov bx,00h

;mov word ptr ds:[bx],5000h ;because jump to 00h,then jump to 5000h in sec3 has error,so jump to 5000h dirctly here

;mov word ptr ds:[bx]+2,0008h

;mov bx,00h

;jmp dword ptr [ebx]

jump <0008h>,<0000h> ;now,sec3 use32,all is ok

; This routine checks that the keyboard command queue is empty

; No timeout is used - if this hangs there is something wrong with

; the machine, and we probably couldn't proceed anyway.

empty_8042:

dw 00ebh,00ebh

in al,64h ; 8042 status port

test al,02h ; is input buffer full?

jnz empty_8042 ; yes - loop

ret

;display,can run in protect mode

showMsg:

mov bx,0020h

mov es,bx

xor di,di

mov bx,0010h

mov ds,bx

mov si,offset strShow

mov cx,30

repeat:

lodsb

stosb

mov al,87h

stosb

dec cx

cmp cx,0

jne repeat

;define the vars

strShow db 'SECTOR2***********SECTOR2***********SECTOR2'

idt_48 dw 0,0,0

gdt dw 0,0,0,0 ; dummy

gdt1 dw 7FFFh,0000h,9A00h,00C0h ; granularity=4096, 386

gdt2 dw 7FFFh,0000h,9200h,00C0h ; 128MB

gdt3 dw 07FFh,0fff0h,9208h,00C0h ; for jmp use,base=8fff0h near the 90000h

gdt4 dw 07FFh,08000h,920Bh,00C0h ; for show Message use,base=b8000h,4MB size

; gdt limit=2048, 256 GDT entries

gdt_48 dw 800h,0200h+gdt,09h ; gdt base = 0X9xxxx

code ends

end start

3。setup.asm,是从setup.s翻译过来的。不过,这里有些改动,我把中断0-F分别用自己的函数实现了,并且加入了两个任务,他们通过TSS相互切换。这里的程序已经是32位的了,且声明支持386指令。内容为:

P386

jump macro selector,offset ;for 32 bit jmp

db 0eah ;

dw offset ;

dw 00h

dw selector ;

endm

call32 macro selector,offset ;for 32 bit call

db 09ah

dw offset

dw 00h

dw selector

endm

code segment use32

assume cs:code,ds:code,es:code

public showMsg

public strShow

pg_dir:

start:

mov ax,10h

mov ds,ax

mov es,ax

mov fs,ax

mov gs,ax

mov ss,ax ;setup ss,sp by nomad

mov esp,0ffffffh ;16MB upper

call setup_idt

call setup_gdt ; load gdt with whatever appropriate

mov ax,10h ; reload all the segment registers

mov ds,ax ; after changing gdt. CS was already

mov es,ax ; reloaded in 'setup_gdt'

mov fs,ax

mov gs,ax

xor eax,eax

A20:

inc eax ; check that A20 really IS enabled

mov ds:[000000h],eax ; loop forever if it isn't

cmp ds:[100000h],eax

je A20

;chach 80287

mov eax,cr0 ; check math chip

and eax,80000011h ; Save PG,PE,ET

; "orl $0x10020,%eax" here for 486 might be good

or eax,02h ; set MP

mov cr0,eax

call check_x87

jmp after_page_tables

;check the 80287/80387*******************

check_x87:

fninit

fstsw ax

cmp al,0

je x87 ;no coprocessor: have to set bits

mov eax,cr0

xor eax,06h ;reset MP, set EM

mov cr0,eax

ret

align 2

x87:

db 0DBh,0E4h ;fsetpm for 287, ignored by 387

ret

;setup the interrupt**********************

setup_idt:

lea edx,ignore_int

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

mov ecx,256

rp_sidt:

mov [edi],eax

mov 4[edi],edx

add edi,8

dec ecx

jne rp_sidt

;lidt qword ptr idt_48

;ret

;add 0-9 interrupt for test

add_int0:

lea edx,int_0

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0

mov [edi],eax

mov 4[edi],edx

add_int1:

lea edx,int_1

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*1

mov [edi],eax

mov 4[edi],edx

add_int2:

lea edx,int_2

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*2

mov [edi],eax

mov 4[edi],edx

add_int3:

lea edx,int_3

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*3

mov [edi],eax

mov 4[edi],edx

add_int4:

lea edx,int_4

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*4

mov [edi],eax

mov 4[edi],edx

add_int5:

lea edx,int_5

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*5

mov [edi],eax

mov 4[edi],edx

add_int6:

lea edx,int_6

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*6

mov [edi],eax

mov 4[edi],edx

add_int7:

lea edx,int_7

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*7

mov [edi],eax

mov 4[edi],edx

add_int8:

lea edx,int_8

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*8

mov [edi],eax

mov 4[edi],edx

add_int9:

lea edx,int_9

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*9

mov [edi],eax

mov 4[edi],edx

add_inta:

lea edx,int_a

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0ah

mov [edi],eax

mov 4[edi],edx

add_intb:

lea edx,int_b

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0bh

mov [edi],eax

mov 4[edi],edx

add_intc:

lea edx,int_c

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0ch

mov [edi],eax

mov 4[edi],edx

add_intd:

lea edx,int_d

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0dh

mov [edi],eax

mov 4[edi],edx

add_inte:

lea edx,int_e

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*0eh

mov [edi],eax

mov 4[edi],edx

add_int10:

lea edx,int_10

mov eax,00080000h

mov ax,dx ;selector = 0x0008 = cs

mov dx,8E00h ;interrupt gate - dpl=0, present

lea edi,idt

add edi,8*10h

mov [edi],eax

mov 4[edi],edx

lidt qword ptr idt_48

ret

;setup the GDT***************************

setup_gdt:

lgdt qword ptr gdt_48

ret

;define the page*************************

org 1000h

pg0:

org 2000h

pg1:

org 3000h

pg2:

org 4000h

pg3:

org 5000h

;tmp_floppy_area is used by the floppy-driver*************

;tmp_floppy_area db 1024*1 dup(0)

; interrupt for test

align 2

int_0:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,30h ;30h=0

call ignore_int

pop eax

int_1:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,31h ;31h=1

call ignore_int

pop eax

int_2:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,32h ;32h=2

call ignore_int

pop eax

int_3:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,33h ;33h=3

call ignore_int

pop eax

int_4:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,34h ;34h=4

call ignore_int

pop eax

int_5:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,35h ;35h=5

call ignore_int

pop eax

int_6:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,36h ;36h=6

call ignore_int

pop eax

int_7:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,37h ;37h=7

call ignore_int

pop eax

int_8:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,38h ;38h=8

call ignore_int

pop eax

int_9:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,39h ;39h=9

call ignore_int

pop eax

int_a:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,41h ;41h=A

call ignore_int

pop eax

int_b:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,42h ;42h=B

call ignore_int

pop eax

int_c:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,43h ;43h=C

call ignore_int

pop eax

int_d:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,44h ;44h=D

call ignore_int

pop eax

int_e:

push eax

mov eax,offset int_msg

mov byte ptr [eax]+7,45h ;45h=E

call ignore_int

pop eax

int_10:

push eax

mov eax,offset int_msg

mov word ptr [eax]+7,3130h ;3130h=10h

call ignore_int

pop eax

after_page_tables:

push 0 ; These are the parameters to main :-)

push 0

push 0

push offset L6 ; return address for main, if it decides to.

push offset main

jmp setup_paging

;call setup_paging

;jump <28h>,<0000h> ;jmp to main for 16 bit code

;jump <08h>,<7000h> ;jmp to main for 32 bit code

L6:

push offset strShow

call showMsg

push offset int_msg

call showMsg

jmp L6 ; main should never return here, but

; just in case, we know what happens.

; This is the default interrupt "handler" :-)************

int_msg db 'Unknown interrupt!',01h,01h

align 2

ignore_int:

push eax

push ecx

push edx

push ds

push es

push fs

mov eax,10h

mov ds,ax

mov es,ax

mov fs,ax

push offset int_msg

call showMsg

pop fs

pop es

pop ds

pop edx

pop ecx

pop eax

iret

;Setup_paging*************************

align 2

setup_paging:

mov cx,1024*5 ; 5 pages - pg_dir+4 page tables

xor eax,eax

xor bx,bx

addr:

mov dword ptr ds:[bx],eax

add bx,04h

cmp bx,5000h

jb addr

mov dword ptr [pg_dir],00001007h ; set present bit/user r/w

mov dword ptr [pg_dir]+4,00002007h ; --------- " " ---------

mov dword ptr [pg_dir]+8,00003007h ; --------- " " ---------

mov dword ptr [pg_dir]+12,00004007h ; --------- " " ---------

mov ebx,1000h ;begin at pg0,

mov eax,00000007h

setpage:

mov dword ptr ds:[ebx],eax

add eax,1000h

add ebx,04h

cmp ebx,5000h ;end at the end of pg4,1024*4 page is 4MB*4=16MB DRAM

jb setpage

xor eax,eax

mov cr3,eax

mov eax,cr0

or eax,80000000h

mov cr0,eax

ret

;showMsg. To show some message**********************

org 5550h ;nomad add for main use

showMsg proc near

;save regesters

push ebp

mov ebp,esp

push ebx

push eax

push es

push edi

push ds

push esi

;do show message

mov ax,0020h

mov es,ax

xor edi,edi

mov ax,0010h

mov ds,ax

mov esi,dword ptr ss:[ebp]+8 ;get string address for stack

repeat:

lodsb

mov bl,al

stosb

mov al,87h

stosb

cmp bl,01h

jne repeat

mov eax,8fffffffh ;to delay sometime

delay:

dec eax

jnz delay

;reserve regesters

pop esi

pop ds

pop edi

pop es

pop eax

pop ebx

pop ebp

pop eax ;stdcall

ret

showMsg endp

;define the vars==================================================

org 5600h ;nomad add for main use

strShow db '********Now is in the Protect mode,and PG is enable!**********',01h,01h

align 2

dw 0

idt_48 dw 256*8-1 ; idt contains 256 entries

dd idt

align 2

dw 0

gdt_48 dw 800h

dd gdt ; magic number, but it works for me :^)

;define the idt====================================

org 5800h ;nomad add for later use,idt is 256*8

align 8

idt db 256*8 dup(0) ; idt is uninitialized

;define the gdt====================================

org 6000h ;nomad add for later use,gdt is 256*8

gdt dw 0,0,0,0 ; NULL descriptor

gdt1 dq 00c09a0000000fffh ; 16Mb,code

gdt2 dw 0FFFh,00000h,9200h,00C0h ; 16MB,data, others same as sec2.asm

gdt3 dw 07FFh,0fff0h,9208h,00C0h ; for jmp use,base=8fff0h near the 90000h

gdt4 dw 0004h,08000h,0F20Bh,00C0h ; for show Message use,base=b8000h,16KB size,DPL=3

gdt5 dw 0FFFh,00000h,9200h,00C0h ; 16MB stack for system use

gdt6 dw 128,06C00h,0E900h,0000h ; for tss,system use

gdt7 dw 8*8,06800h,08200h,0000h ; for ldt,8 segment,task 0,DPL=3

gdt8 dw 128,06C80h,0E900h,0000h ; for tss, task 0

gdt9 dw 8*8,06840h,8200h,0000h ; for ldt,8 segment,task 1=task 0+8*8

gdta dw 128,06D00h,0E900h,0000h ; for tss, task 1=task 0+128

;define the ldt====================================

org 6800h ;nomad add for later use,ldt is 128*8=400h

ldt dw 0,0,0FA00h,0 ;dummy,DPL=3

code0 dw 0001h,07100h,0FA00h,00C0h ;code,dpl=3

data0 dw 0001h,07200h,0F200h,00C0h ;data,dpl=3

cGate dw 7080h,00008h,08C00h,0000h ;Gate,go to main,DPL=3

tGate dw 0000h,00030h,0E500h,0000h ;Gate,go to main,DPL=3

org 6840h ;task 1

ldt1 dw 0,0,0,0 ;dummy

code1 dw 0001h,07300h,0BA00h,00C0h ;code,DPL=1

data1 dw 0001h,07400h,0B200h,00C0h ;data,DPL=1

cGate1 dw 7000h,00008h,08C00h,0000h ;Gate,go to main

tGate1 dw 0000h,00030h,0E500h,0000h ;Gate,go to main,DPL=3

;define the TSS====================================

org 6C00h ;for tss 0 is used by system, 6C00h-7000h is 400h=128(80h)*8

tss dd 0 ;back

dd 0FFFFF0h ;esp0,16MB

dw 28h,0 ;ss0

dd 0F0H ;esp1

dw 14h,0 ;ss1

dd 0F0H ;esp2

dw 14h,0 ;ss2

dd 00h ;cr3

dd 00h ;eip

dd ? ;eflasgs

dd ? ;eax

dd ? ;ecx

dd ? ;edx

dd ? ;ebx

dd 0F0h ;esp

dd ? ;ebp

dd ? ;esi

dd ? ;edi

dw 14h,0 ;es

dw 0Ch,0 ;cs

dw 14h,0 ;ss

dw 14h,0 ;ds

dw 14h,0 ;fs

dw 14h,0 ;gs

dw 38h,0 ;ldt

dw 0,0 ;io

db 0ffh

org 6C80h ;for tss 1

dd 0 ;back

dd 0FFFFF0h ;esp0,16MB

dw 28h,0 ;ss0

dd ? ;esp1

dw ?,0 ;ss1

dd ? ;esp2

dw ?,0 ;ss2

dd 00h ;cr3

dd 00h ;eip

dd ? ;eflasgs

dd ? ;eax

dd ? ;ecx

dd ? ;edx

dd ? ;ebx

dd 0F0h ;esp

dd ? ;ebp

dd ? ;esi

dd ? ;edi

dw ?,0 ;es

dw 0Fh,0 ;cs,RING3

dw 17h,0 ;ss,RING3

dw ?,0 ;ds

dw ?,0 ;fs

dw ?,0 ;gs

dw 38h,0 ;ldt

dw 0,0 ;io

db 0ffh

org 6D00h ;for tss 2

dd 0 ;back

dd 0FFFFF0h ;esp0,16MB

dw 28h,0 ;ss0

dd ? ;esp1

dw ?,0 ;ss1

dd ? ;esp2

dw ?,0 ;ss2

dd 00h ;cr3

dd 00h ;eip

dd ? ;eflasgs

dd ? ;eax

dd ? ;ecx

dd ? ;edx

dd ? ;ebx

dd 0F0h ;esp

dd ? ;ebp

dd ? ;esi

dd ? ;edi

dw ?,0 ;es

dw 0Dh,0 ;cs,RPL=1

dw 15h,0 ;ss,RPL=1

dw ?,0 ;ds

dw ?,0 ;fs

dw ?,0 ;gs

dw 48h,0 ;ldt

dw 0,0 ;io

db 0ffh

org 6D80h ;for tss 3

org 6E00h ;for tss 4

org 6E80h ;for tss 5

org 6F00h ;for tss 6

org 6F80h ;for tss 7

;define the main===================================

org 7000h ;nomad add for main function point here

main:

;**use ldt,can easy jmp to task0 and task1*********************

;mov ax,0038h ;gdt7 for task0,ldt

;lldt ax

;jump 000Ch,0000h

;call32 000ch,0000h

;org 7080h ;task1

;mov ax,0048h ;gdt9 for task1

;lldt ax

;jump 000Ch,0000h

;**use retf of call from stack,can change from ring0 to ring3**

;mov ax,0038h ;gdt7 for task0,ldt

;lldt ax

;push 0017h ;ss,RPL=3

;push 00F0h ;esp

;push 000Fh ;cs,RPL=3

;push 0000h ;eip

;retf ;can't use ret

;**can chang task use tss,from ring0 to ring3******************

mov ax,0030h ;tss for system

ltr ax

redo:

jump 0040h,0000h

jump 0050h,0000h

jmp redo

;task 0************************************

org 7100h ;code

task0:

mov ax,0020h

mov es,ax

xor edi,edi

mov ax,0014h

mov ds,ax

xor esi,esi

repeat0:

lodsb

mov bl,al

stosb

mov al,87h

stosb

cmp bl,01h

jne repeat0

mov eax,8fffffffh ;to delay sometime

delay0:

dec eax

jnz delay0

;jump 0024h,0000h ;to ldt sel

jump 0030h,0000h ;jmp to main tss

jmp task0

org 7200h ;data and stack

strTask0 db 'There is the task 0 ! ',01h,01h

;task 1************************************

org 07300h ;code

task1:

mov ax,0020h

mov es,ax

xor edi,edi

mov ax,0014h

mov ds,ax

xor esi,esi

repeat1:

lodsb

mov bl,al

stosb

mov al,87h

stosb

cmp bl,01h

jne repeat1

mov eax,8fffffffh ;to delay sometime

delay1:

dec eax

jnz delay1

jump 0024h,0000h ;to ldt sel

jmp task1

org 07400h;data and stack

strTask1 db 'There is the task 1++++',01h,01h

code ends ;so the sec3's code is 7000h,equel 28 sectors,and main will begin from 7000h

end start

我在setup.asm中加入了两个任务,并用TSS切换他们之间的运行。于是可以在屏幕上交替输出“There is the task 1++++”和“There is the task 0 !”字符串

十一个月宝宝半夜发烧怎么办
肾炎晚上尿多吗
九个月宝宝吸收不好怎么办
热淋清颗粒的主要成分
分享到: