• Linux0.11内核--引导程序分析


    1.简介

    本文主要介绍三个文件bootsect.s、setup.s、head.s,主要是做了些从软盘加载内核和设置32位保护模式的操作。

    2.程序分析

    当PC电源打开后,BIOS自检后将bootsect读入内存绝对地址0x7c00处,因为bootsect.s的结尾是:

    	.word 0xAA55
    

    然后跳转到0x7c00处并把执行权交给此处的代码,从start:处开始执行。

    BOOTSEG  = 0x07c0	
    INITSEG  = 0x9000
    
    start:
    	mov	ax,#BOOTSEG
    	mov	ds,ax
    	mov	ax,#INITSEG
    	mov	es,ax
    	mov	cx,#256
    	sub	si,si
    	sub	di,di
    	rep
    	movw
    	jmpi	go,INITSEG
    

    BOOTSEG是当前程序的起始内存地址的段地址,INITSEG表示是bootsect将要移动要的内存地址的段地址,这段代码的意思是重复执行movw指令256次,每次从BOOTSEG(0x7c0段地址)+si的地址处移动一个字(2个字节)的数据到INITSEG(0x9000段地址)+di地址处,挨个移动256次,所以总共就是256字(512字节),bootsect.s编译出来也就是512字节的大小。所以这段代码执行完之后就是把自己拷贝到0x90000地址处,然后jmpi跳转到0x9000的偏移地址为go的地方执行。

    所以接下来程序执行到go:处,但是整个程序的起始段地址变成了0x9000,go处的代码设置了下堆栈,接着是load_setup:

    SETUPLEN = 4	
    
    load_setup:
    	mov	dx,#0x0000		! drive 0, head 0
    	mov	cx,#0x0002		! sector 2, track 0
    	mov	bx,#0x0200		! address = 512, in INITSEG
    	mov	ax,#0x0200+SETUPLEN	! service 2, nr of sectors
    	int	0x13			! read it
    	jnc	ok_load_setup		! ok - continue
    	mov	dx,#0x0000
    	mov	ax,#0x0000		! reset the diskette
    	int	0x13
    	j	load_setup
    

    利用BIOS中断int 0x13将setup从磁盘第2个扇区开始读到0x90200开始处,共SETUPLEN(setup 程序的扇区数)读4个扇区。成功后跳转到ok_load_setup。

    SETUPSEG = 0x9020
    
    ok_load_setup:
    ...
    	mov	ax,#SYSSEG
    	mov	es,ax		! segment of 0x010000
    	call	read_it
    	call	kill_motor
    
    ...
    	jmpi	0,SETUPSEG
    

    省略的代码都是一些读硬盘和驱动器的数据。这里比较关键的是call read_it,调用read_it:

    SYSSIZE = 0x3000
    SYSSEG   = 0x1000
    ENDSEG   = SYSSEG + SYSSIZE
    
    read_it:
    	mov ax,es
    	test ax,#0x0fff
    die:	jne die			! es must be at 64kB boundary
    	xor bx,bx		! bx is starting address within segment
    rp_read:
    	mov ax,es
    	cmp ax,#ENDSEG		! have we loaded all yet?
    	jb ok1_read
    	ret
    ok1_read:
    	...
    

    SYSSIZE是编译后system模块的大小,SYSSEG是system模块将加载到的内存段地址处,所以ENDSEG的值就是system模块停止加载的段地址。那么read_it的作用就是先判断一下es是不是到了system模块停止加载的段地址处,如果没有则跳转去读取system模块到这个地址。加载完成后就ret返回。然后关闭马达后读一些驱动器的信息,最后jmpi 0,SETUPSEG跳转到0x9020:0000也就是setup.s程序的开始处。

    bootsect.s就此结束,到现在为止内核各个模块在内存中的位置如下图的第3步:

    接下来进入setup.s。

    未完待续

  • 相关阅读:
    telnet c# 执行命令
    C# Windows服务安装、卸载批处理代码
    数据库高人 邹健 博客链接
    HDOJ_1232 并查集 畅通工程
    poj3461 KMP 小结
    HDOJ_2094 寻找冠军 set的简单应用
    HDOJ_1272 小希的迷宫 并查
    HDOJ_2754 素数种类统计
    linux下的jsp
    mysql
  • 原文地址:https://www.cnblogs.com/joey-hua/p/5528228.html
Copyright © 2020-2023  润新知