编写实模式多任务操作系统模型之(2)

程序模块分析


本操作系统模型由两个程序组成,一个为引导程序boot.asm,另一个为内核程序kernel.asm。其中引导程序位于软盘的引导扇区,主要功能为将Kernel从盘上读入内存,让其运行;Kernel则依次使3个进程占用CPU,完成各自的工作。

引导程序boot.asm

引导程序boot.asm位于引导软盘的0面0道1扇区,共计512个字节长度。该段程序在系统通电自检完成后,将由ROMBIOS读到内存的0000:7c00h地址处,并从该地址开始执行。该程序运行后将首先将自身移动到高端内存区9000:7c00h,留出低端内存区以备功能扩展时使用,而后转到高端内存区执行。接着对引导驱动器复位,利用int 13h的物理读盘功能,将位于0头0道2扇区及3扇区的kernel程序读入内存 8000:0000h地址处。若读盘失败,则进行3次尝试;若仍未读出,则显示“kernel Loading failed ! Any key to reboot...” 信息,而后重新启动;若读盘成功,则跳到kernel程序的入口点8000:0000h地址处执行。程序流程如图1所示。



boot.asm执行后的内存布局如图2所示。由于在实模式下编程,程序可访问的内存空间为1MB,绝对地址从00000H~FFFFFH,其中低端内存及高端内存的部分区域已经被系统占用,程序可用的内存区为位于高端及低端的中间部分。由于本程序规模较小,内存空间足够用。对于本程序,高端97C00H~97DFFH为引导程序自搬移后的位置,80000H~803FFH为成功读入的内核代码所占的内存空间。



boot.asm的程序代码及详细注释如下:

     
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; boot.asm - OS 引导扇区程序Bootloader
;; 功能: 将自身移动至内存高端,而后将启动盘上的kernel读到内存,
;;       接着跳转到kernel....
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[BITS 16]	                     ;实模式 16bit 代码结构 
; 标号等价伪定义
	INITSEG      EQU 0x07c0	     ; 启动扇区段地址 
	NEWSEG	     EQU 0x9000      ; 引导程序移动到的高端段地址 
        KERNELSEG    EQU 0x8000      ; kernel段地址  
        KERNELOFFSET EQU 0x0000      ; kernel偏移地址
        REBOOTSEG    EQU 0XFFFF      ; 重启动段地址 
        REBOOTOFFSET EQU 0X0000      ; 重启动偏移地址 
org 0x7c00		             ; 汇编起始地址 
start:
jmp short bootup	   ;跳转到启动代码 
; 数据区 
; 变量定义 
     bootdrv db 0          ;bootdrv用于保存启动驱动器号
     retries db 3	   ;重复读盘次数
     ;系统启动信息
     bootmsg db "System bootup ... ",0dh,0ah,00h 
     ; kernel loading 信息
     loadknlmsg db "Loading kernel ... ",0dh,0ah,00h
     ; kernel loading 错误信息
     loadknlerrmsg db "Kernel loading failed !",0dh,0ah,"Any key to 
reboot...",0dh,0ah,00h
bootup:                         
    	mov [bootdrv], dl	  ; 保存启动驱动器号
    	; 显示启动信息
    	mov si, bootmsg
    	call dispstr
    	; 将自身的所有程序及数据由 0000:7c00h 移动到
    	; 内存高端 9000:7c00h,总计 512 字节长度
	cld			   ; 方向标志置 0, 
	mov ax, NEWSEG             ; ax=0x9000
	mov es, ax	           ; 附加段寄存器es设为 0x9000,所移数据的目的段 
	mov di, start		   ; 目的变址寄存器 =7c00h
	mov si, start		   ; 源变址寄存器 = 7c00h
	mov cx, 0x200		   ; 移动总字节长度 512 Bytes
	cli			   ; 禁止中断 
	rep movsb		   ; 执行移动操作 
	; 跳转到移动后的新段,从 there 地址开始执行.
	JMP NEWSEG:there
	there:	                   ;这里是新的执行起始点.
	sti		           ;开中断 
	;下一步,将kernel 程序从启动驱动器的读到内存中,而后由kernel接管控制.
	mov si,loadknlmsg	
	call dispstr               ;显示kernel 加载信息"kernel loading..."
readagain:
	mov ah, 0		
     	mov dl, [bootdrv]       
	int 0x13		   ; 复位启动驱动器 
        ; 将位于从物理2扇区开始的2个扇区的kernel 程序从启动驱动器的读到内存中
        ; KERNELSEG:0000h
	cld			   ; 方向标志置 0 
     	mov bx, KERNELOFFSET       ; kernel 地址偏移
	mov ax, KERNELSEG	   ; kernel 段地址 0x8000
	mov es, ax
	mov ax, 0x0202	           ; AH = 02 (读扇区功能号), AL=2 (扇区数)
	mov cx, 0x0002		   ; CH - 磁道号, CL - 逻辑扇区号 
	mov dh, 0		   ; DH - 磁头号 
	mov dl, [bootdrv]	   ; DL - 驱动器号 
	int 0x13		   ; 读扇区 BIOS 调用 
	jnc gotoknl		   ; 无错误则进入kernel执行
	dec byte [retries]         ; 读盘计数器减1
	jnz readagain              ; 未到最大读盘次数,则继续读
	mov si,loadknlerrmsg       ; 到达最大读盘次数仍然读盘有错,
	call dispstr               ; 则显示错误信息
	mov ah,0
	int 16h                    ; 等待用户输入任一键
	jmp REBOOTSEG:REBOOTOFFSET ; 重新启动
gotoknl:	
        jmp KERNELSEG:KERNELOFFSET ; 跳到内核代码去执行,启动扇区引导程序结束. 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;字符串显示子程序 dispstr
;参数:si=字符串首地址,字符串以00h作为结束标记
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dispstr:      
        push ax  
        mov ah, 0eh
dispnext:        
        lodsb
        cmp al,0
        jz quit
        int 10h
        jmp dispnext 
quit:   pop ax  
        ret        
times 510-($-$$)   db 0               ; 将空闲的程序区域填充为 00h
	           dw 0xaa55          ; 由BIOS检测的有效的启动扇区标志
;boot.asm结束


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值