李志军老师操作系统实验一笔记+实验代码注释

bootsect.S

使用大S的原因:使用这样的后缀可以让 as 使用 GNU C 编译器的预处理功能,因此可以在汇编语言程序中包括"#include"、 “#if"等语句。本程序使用大写后缀主要是为了能在程序中使用”#include"语句来包含进 linux/config.h 头文件定义的常数。–引自《Linux内核完全注释》
部分代码解读:

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

SETUPLEN = 4				! nr of setup-sectors
BOOTSEG  = 0x07c0			! original address of boot-sector
INITSEG  = DEF_INITSEG			! we move boot here - out of the way
!下面先把自己移动到0x90000处,代码重定位
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 !段间跳转
    !这里go赋值给ip,ip是自start开始到标号go的段内偏移地址
    !INITSEG = 0X9000赋值给cs
!代码重定位后,从这里开始执行,因为ip为go处这个偏移地址
go:	mov	ax,cs		
	mov	dx,#0xfef4	! arbitrary value >>512 - disk parm size

	mov	ds,ax
	mov	es,ax
	push	ax

	mov	ss,ax		! put stack at 0x9ff00 - 12.
	mov	sp,dx
    !把cs = 0x9000这个段基址赋值给ds段,es段和ss段。
    !栈偏移地址这里为0xfef4,可能0.11版本中给了0xff00
    !这样setup在内存中的存放位置就设置好了,并且我们可以看到栈的大小也搞定了
!开始读setup模块的程序了。
!0x13是BIOS读磁盘扇区的中断:
! ah = 0x02 - 读磁盘扇区到内存; al = 需要读出的扇区数量;
! ch = 磁道(柱面)号的低 8 位; cl = 开始扇区(0-5),磁道号高2(6-7)! dh = 磁头号; dl = 驱动器号(如果是硬盘则位 7 要置位);
! es:bx 它指向数据缓冲区; 如果出错则 CF 标志置位, ah 中是出错码。
load_setup:
	xor	dx, dx			! 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
    
!后面读不懂
	push	ax			! dump error code
	call	print_nl
	mov	bp, sp
	call	print_hex
	pop	ax	
	
	xor	dl, dl			! reset FDC
	xor	ah, ah
	int	0x13
	j	load_setup

启动盘的程序放置顺序:
李志军老师操作系统实验一笔记+实验代码注释_第1张图片
很简单,在第二个扇区开始读取4个扇区的内容。

! 这段代码利用 BIOS INT 0x13 功能 8 来取磁盘驱动器的参数。 实际是取每磁道扇区数,并保存在
! 位置 sectors 处。
! Get disk drive parameters, specifically nr of sectors/track
load_setup:
	xor	dl,dl
	mov	ah,#0x08		! AH=8 is get drive parameters
	int	0x13
	xor	ch,ch
	seg cs
	mov	sectors,cx
	mov	ax,#INITSEG
	mov	es,ax

! 下面利用 BIOS INT 0x10 功能 0x030x13 来显示信息:“ 'Loading'+回车+换行”,显示包括
! 回车和换行控制字符在内共 9 个字符。
	mov	ah,#0x03		! read cursor pos
	xor	bh,bh
	int	0x10
	
	mov	cx,#9
	mov	bx,#0x0007		! page 0, attribute 7 (normal)
	mov	bp,#msg1
	mov	ax,#0x1301		! write string, move cursor
	int	0x10
    !下面要读入系统了
    mov	ax,#SYSSEG  !系统代码初始地址为0x1000
	mov	es,ax		! segment of 0x010000
	call	read_it !原来系统放在es段,这里调用的read_it应该是复制系统代码到0x1000处
	jmpi 0,SETUPSEG ! 同前,0赋值给ip,这里因为要执行setup代码了,所以cs为SETUPSEG = 0X9020

下面是李老师的bootsect.s代码以及其完全注释,这部分代码的主要功能有两个。一是显示一段字符“Hello…”,用以与用户进行交互,而是将setup的代码从软驱中读入内存,放到512个字节的bootsect代码之后。最后,程序跳到setup代码中去执行。(TIPS:这里使用//是为了注释方便,该代码可能并无执行能力,仅供学习)

!BOOTSECT.S
SETUPLEN=2          //setup代码的长度为两个扇区,512个字节
SETUPSEG=0x07e0     //setup代码在内存中的执行地址,比0x7c0多0x20,这0x20可能是作为数据段
entry _start        //可能是编译器要读的代码,给编译器解释了程序入口地址是_start
_start:			    //程序入口地址
    mov ah,#0x03    //显示屏打印中断的寄存器赋值操作(这里是读入光标位置)
    xor bh,bh       //显示操作,字节型数据清零用xor(要记住)
    int 0x10	    //寄存器赋值完毕后的显示中断
    mov cx,#36		//显示36个字节,显示的字节在msg1处,注意有要加上换行符和回车符
    mov bx,#0x0007  //显示屏打印中断的寄存器赋值操作(这里是读入一些字符)
    mov bp,#msg1    //bp是es段的偏移地址,这句指令表示字符串的偏移地址在msg1所代表的地址处
    mov ax,#0x07c0  //0x07c0赋值要先赋值给ax是因为段寄存器一般不能直接赋值
    mov es,ax		//为了找到字符串的存放位置我们必须把es段与cs段重合,这样才好定位msg1的偏移地址
    mov ax,#0x1301  //显示屏打印中断的寄存器赋值操作
    int 0x10		//显示中断,执行完这一步,屏幕就能显示一段字符串了。
load_setup:
    mov dx,#0x0000  //设置驱动器和磁头(drive 0, head 0): 软盘 0 磁头
    mov cx,#0x0002	//设置扇区号和磁道(sector 2, track 0): 0 磁头、0 磁道、2 扇区
    mov bx,#0x0200  //设置读入的内存地址:BOOTSEG+address = 512,偏移512字节
    mov ax,#0x0200+SETUPLEN  //SETUPLEN是读入的扇区个数,我们设置为2
    int 0x13				 //应用 0x13 号 BIOS 中断读入 2 个 setup.s扇区
    jnc ok_load_setup		 //读入成功,跳转到 ok_load_setup: ok - continue
    mov dx,#0x0000			 //软驱、软盘有问题才会执行到这里。
    mov ax,#0x0000			 //这句和上一句都是reset软驱操作
    int 0x13				 //复位软驱 reset the diskette
    jmp load_setup			 //跳到load_setup重复步骤,如果这部分一直不过就死机了啊><!!!
ok_load_setup:
    jmpi    0,SETUPSEG  	//众所周知,段寄存器是不能随便赋值的,所以这里采用段间跳转
    						//这里0赋值给ip,INITSEG = 0X07e0赋值给cs(setup代码的执行地址)
msg1:						//字符串存放在这儿
    .byte   13,10			//1对回车、换行 (2字节)
    .ascii  "Hello OS world, my name is LZJ" //屏幕上显示的ascii字符 (30字节)
    .byte   13,10,13,10 	 //2对回车、换行(4字节)
.org 510					//指定510地址,后面的程序或数据从这个地址值开始分配。相当于把代码长度拉满512Kbyte。
boot_flag:					//bootsect的标识符地址,不清楚该标识符具体作用
    .word   0xAA55 			//该语句偏移地址为510,该语句占用2个字节,从而使bootsect代码正好为512字节。

你可能感兴趣的:(李志军老师操作系统实验一笔记+实验代码注释)