⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boot.asm

📁 一个小型的操作系统,采用gcc进行开发,几千行的代码,方便初学者学习
💻 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 + -