科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件Windows编译环境下的Linux启动代码

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这是可以在Windows下编译,并写入软盘执行的linux启动代码。其中包含了如何启动使用386CPU的保护模式、分页机制、任务切换,如何使用GDT、LDT、C0、C3、TSS等。

作者:浪人BLUE 来源:CSDN 2008年3月27日

关键字: Linux 编译环境 Windows 开源

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

 

 

 

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

 

 

 

1bootsect.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

2setup.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

3setup.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 !”字符串

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章