📄 boot.asm
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Snixos Project version 1.0, 2003.6
; (C) Copyright 2003,2004,2005 Jockeyson,KeqiangGao <Snallie@tom.com>
; All Rights Reserved.
; Distributed under the terms of the GNU General Public License.
;
; This program is a free and open source software and you can redistribute
; it and/or modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation. As no any liability is assumed
; for any incidental or consequential damages in connection with the
; information or program fragments contained herein,so any exception arised
; is at your own risk. It is ABSOLUTELY WITHOUT ANY WARRANTY. Any bugs or
; errors reported to Snallie@tom.com or Snallie@tom.com is highly appreciated.
;
; boot.asm: bootloader for Snixos project
; author : Jockeyson KeqiangGao <snallie@tom.com>
; time : 2003.6
; version : ver 0.1
; Abstract: This is the floppy bootloader program for Snixos project,
; an experimental operating system based on IA32 CPU. After
; it is compiled with 'NASM', a binary file will be produced,
; write it to the floppy disk with 'rawrite' under DOS or
; 'dd' in UNIX, and you'll get a boot disk for Snixos.
;
; Compiling Environment:
; Linux/NASM, DOS/NASM
;
; to make : nasm -f bin boot.asm -o boot.bin
;
; What it did:
; 0. bootloader resided in the first sector of boot floppy
; while building disk.
; 1. when PC bootup, bootloader is read by ROMBIOS into
; memory addressed by 0:7c00h, i.e. linearly 07c00h.
; 2. bootloader read the kernel into memory addressed
; by 0x8000:0h , linearly 00080000h,the kernel starting
; from the 2nd sector of floppy, length depended on the
; actually compiled result.
; 2.1 hzk16 is resided on track 10 of boot floppy , it is read
; to 0x:2000:0~..., and in kernel , hzk16 is saved as a
; ramdisk file name hzk16 for Chinese character manipulation
; 2.2 py.mb is resided on track 40 of boot floppy , it is read
; to 0x:7000:0~..., and in kernel , py.mb is saved as a
; ramdisk file name py.mb for Chinese character manipulation
; 3. initializing the GDT table, then move the GDT table
; to linear address 00h the very beginning of physical
; memory.
; 4. switching to protected mode, then jmp to kernel
; resided in 00080000h , read by the 2nd step above,
; and the totally control is under the kernel program.
;
; Revision History:
; $Revision$
; $Log$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;###########################################################################
; pseudo symbol definition area
;###########################################################################
KERNELSEG EQU 0x8000 ; kernel segment address
KERNELOFFSET EQU 0x0000 ; kernel offset address
REBOOTSEG EQU 0XFFFF ; PC reset routine segment address
REBOOTOFFSET EQU 0X0000 ; PC reset routine offset address
SECTORSPERTRACK EQU 18 ; sectors per track of 1.44M floppy
BYTESPERSECTOR EQU 512 ; bytes per sector occupied of floppy
SYSSIZE EQU 0xf000 ; must be matched with the length of
; kernel.bin when varied, a bit larger anyway
CNFONTSEG EQU 0X2000 ; where hzk16 be stored
PYMBSEG EQU 0X7000 ; mabiao for Chinese pinyin input method
[BITS 16]
[ORG 0x7C00] ; assembler init address 0000:7c00
jmp bootup ; jump to boot entrance
;###########################################################################
; subroutine definition area
;###########################################################################
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; print_mesg: print string via ROMBIOS int 10h
; arg: si=starting address of string ,ended with ASCII zero 00h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
print_mesg:
push ax
mov ah, 0eh
dispnext:
lodsb
cmp al,0
jz quit
int 10h ; BIOS 10h ah=0eh
jmp dispnext
quit: pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; waitKey: wait any key from keyboard
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
waitKey:
mov ah,0
int 16h
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;clrscr: clear screen
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
clrscr:
mov ax,0x0700 ; clear screen
mov cx,0x0000
mov dx,0x174f
mov bh,0x07 ; white on black attribute
int 0x10
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ReadSectorsToMem : read certain sectors to memory
; Input parameters:
; es:bx= destination memory for data storing
; ch = track number
; cl = starting sector number
; dh = head number
; dl = drive number
; [fontsectors]= sectors to be read
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ReadSectorsToMem:
readon:
call ReadOneSector ; each track has 512*18=9k bytes , read 1 sector
dec word [fontsectors]
jz fontok ; font totally read to 0x02000:0
cmp bx,0
je got64k ; 64k have got , adjust es
nextSect:
cmp cl,SECTORSPERTRACK-1 ; reached the end of the current track ?
ja clSet1_AlternateDH
inc cl
jmp readon
got64k: push ax
mov ax,es
add ax,0x1000 ; move ES to the next 64K boundary
mov es,ax
pop ax
jmp nextSect
clSet1_AlternateDH:
mov cl,1
inc dh ; head varied
and dh,0x01
cmp dh,0
jnz sametrk2
inc ch ; switch to nextTrack
sametrk2:
jmp readon
fontok: ret
ReadOneSector: ; read a sector of 512 bytes
mov ah,2 ; read sector function call for int 13h
mov al,1 ; only 1 sector to be read each time
mov dl,[bootdrv]
call readFlpData
call printDot ; print "." to indicate a sector has been read ok
add bx,512 ; bx = bx + (bytes just read)
ret
; end of ReadOneSector
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; printDot:
; routine for print a '.'(0x2e) on screen
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printDot:
push ax
mov ax,0x0e2e
int 0x10
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; readFlpData: routine for read data from floppy,assuming
; that all parameters have been prepared in
; CPU register AX,BX,CX,DX. For each data, it
; makes 3 attempts to read, if retries exceeded
; the retry attempts, it will reboot after a
; prompt message
; "Kernel loading error! Any key to reboot..."
; displayed.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
readFlpData:
push ax
push bx
push cx
push dx
int 0x13
jnc readOK
xor ax,ax
xor dx,dx
int 0x13 ; reset floppy if reading failed
dec byte [retries]
jz .lderr
pop dx
pop cx
pop bx
pop ax
jmp readFlpData
.lderr
mov si, loadknlerrmsg
call print_mesg
call waitKey
jmp REBOOTSEG:REBOOTOFFSET ; reboot PC after all attempt exhausts
jmp $ ; hangup
readOK:
mov byte [retries],3 ; restore times for reading attempt
pop dx
pop cx
pop bx
add sp,2 ; save ax because al is the tracks it've read
ret
; subroutine readFlpData ended here
; !!! bootup !!!,this is the destination of the JMP instruction when bootloader
; take control of pc
bootup:
xor ax,ax
mov ds,ax ; ds=cs=0
mov ss,ax
mov [bootdrv],dl ; save boot drive from dl
mov sp,0xffff ; init stack
call clrscr ; clear screen
mov ah,2
mov dx,0 ; cursor position 0,0
mov bh,0 ; video page 0
int 10h ; set cursor to 0,0
mov si,bootmesg
call print_mesg ; display "Starting SNIXOS..",
; each dot means one track has been read
; load kernel from disk through int 13h
loadKernel:
mov ax,KERNELSEG ; 0x8000
mov es,ax
xor bx,bx ; es:bx=8000:0h where hzk16 will be loaded here
mov cx,0x0002 ; ch = track number, cl = starting sector number
mov dx,0x0000 ; dh = head number, dl = drive number
mov ax,100
mov [fontsectors],ax
call ReadSectorsToMem ; load kernel from chs=002 to 0x80000
; if macro VIDEO_GRAPH_640X480 is defined , prepare hzk16 and
; graphics mode of video for the Chinese environment , else
; skip the lines below
%ifdef VIDEO_GRAPH_640X480
; read cnfontlib hzk16 to 0x2000:0, hzk16 resided on boot floppy track 10
mov si,fontmesg
call print_mesg ; display "Reading hzk16",
mov ax,CNFONTSEG ; 0x2000
mov es,ax
xor bx,bx ; es:bx=2000:0h where hzk16 will be loaded here
mov cx,0x0a01 ; ch = track number, cl = starting sector number
mov dx,0x0000 ; dh = head number, dl = drive number
mov ax, 523
mov [fontsectors],ax
call ReadSectorsToMem
mov si,pymbmesg
call print_mesg ; display "Reading pymb",
mov ax,PYMBSEG ; 0x7000
mov es,ax
xor bx,bx ; es:bx=7000:0h where py.mb will be loaded here
mov cx,0x2801 ; ch = track number, cl = starting sector number
mov dx,0x0000 ; dh = head number, dl = drive number
mov ax,46
mov [fontsectors],ax
call ReadSectorsToMem
; set VGA 640*480 monochrome for Chinese environment
mov ah,0
mov al,11h
int 10h
%endif
; if program goes here, it means that kernel loaded ok by procedure readKernel
; and it begin the phase for entering X86 protected mode below
pre_goto_pm: ; prepare to switch to PM mode
mov dx,0x3f2
mov al,0x0c
out dx,al ; stop floppy motor
; prepare for PM mode
cli ; clear interrupt, don't forgot enabling it
push es
xor ax, ax
mov es, ax
xor di, di
mov si, gdt
mov cx, gdt_end-gdt
rep movsb ; move gdt to linear address 0x00000000
pop es
; the below to enable PM mode
lgdt [gdtr] ; load GDT
mov eax,cr0
or al,0x01
mov cr0,eax ; enable bit 0 of CR0 register
; Enabling A20 gate for the accessing the memory which above 1M
in al, 0x92
or al, 2
out 0x92, al
jmp codesel:go_pm ; PM mode enabled ,now memory accessed as
; segmentSelector:32bitsOffset
[BITS 32]
go_pm:
mov ax,datasel
mov ds,ax ; init ds,es->data seg
mov es,ax
mov ss,ax
mov fs,ax
mov gs,ax
mov esp,0x9fff0 ; init system stack esp=0x9fff0, upper memory
; about to entering kernel ,
; remember to enable interrupt with STI while everything is OK
jmp codesel:0x80000 ; jmp to kernel that have been read from disk
; chs:002, and never return.
;;bootloader done here
;###########################################################################
; data definition area below
;###########################################################################
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;data to be load to gdtr register in CPU
;gdtr register (48bits) contains: WORD1: length of gdt
; REST(32BITS): physical address of gdt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr:
dw 0x1000 ; length of gdt
dd 0 ; linearly 0x00
; The interrupt descriptor table, nothing here has yet,
; will be loaded in kernel
idtr:
dw 0
dd 0x1000
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;gdt table (each occupied 8 bytes)
;start addr: gdt
;end addr : gdt_end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt
nullsel equ $-gdt ; $ denotes current address while assembling,
; so nullsel = 0h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Intel reserved for the first descriptor
;in gdt filled with blank
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt0 ; first descriptor
dd 0 ; filled with null
dd 0 ; of 8 bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; code descriptor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
codesel equ $-gdt ; codesel=8h, the 2nd descriptor in gdt
code_gdt
dw 0x0ffff ; 4 GB limit
dw 0x0000 ; Base zero L
db 0x00 ; Base zero M
db 0x09a ; non-comforming exec segment
db 0x0cf ; Granularity 4k
db 0x00 ; Base zero H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; data descriptor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
datasel equ $-gdt ;datasel=16
data_gdt
dw 0x0ffff ;LENGTH OF SEGMENT
dw 0x0000 ;BASEADDR OF SEGMENT i.e.
db 0x00 ;base (16-23) 32-39
db 0x092
db 0x0cf
db 0x00 ; base (24-31) 24-31
gdt_for_ldt_tss:
;.fill 252,8,0 ; space for LDT's and TSS's etc
gdt_end ;gdt ended here
bootmesg db "Starting SNIXOS",0
loadknlerrmsg db 10,13,"Kernel loading error! Any key to reboot",0
sectors db SECTORSPERTRACK -1
bootdrv db 0 ; boot drive number
retries db 3 ; retries of read boot sector while failure occured
fontmesg db 10,13, "Reading hzk16",0
pymbmesg db 10,13, "Reading py.mb",0
fontsectors dw 523 ; 267616/512+1
;pymbsecrots dw 46 ; 23502/512+1
times 510-($-$$) db 0 ; all the rest filled with blank
dw 0x0aa55 ; signature required by certain BIOS
;; boot.asm ended here
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -