说明一下,这里省略了一些print信息,目的是为了使代码短一些,而且print信息的代码都很简单,大家有兴趣可以自己读一下。
#include <linux/config.h> /* for CONFIG_ROOT_RDONLY */
#include <asm/boot.h>
// 我把这些宏的定义都列在下面了。
SETUPSECS =4 /* default nr ofsetup-sectors */
BOOTSEG =0x07C0 /* original address ofboot-sector */
INITSEG =0x9000 /* we move boot here - out of theway */
SETUPSEG =0x9020 /* setup starts here */
SYSSEG =0x10000 /* system loadedat 0x10000 (65536) */
SYSSIZE =0x7F00 /* system size: # of16-byte clicks */
/* to be loaded */
ROOT_DEV =0 /* ROOT_DEV is nowwritten by "build" */
SWAP_DEV =0 /* SWAP_DEV is nowwritten by "build" */
#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif
#ifndef RAMDISK
#define RAMDISK 0
#endif
#ifndef CONFIG_ROOT_RDONLY
#define CONFIG_ROOT_RDONLY 1
#endif
// 在此这上的部分,是不会出现在编译运行的二进制中的,这一部分内容只是汇编器所需要的信息
//下面是真正运行的代码了
.code16 // 表示下面的代码运行在16位模式下
.text
.global _start //global标签的意思是让链接器可以看到_start符号。
_start:
/* section 1的内容很简单,开机上电bios会把启动设备的一个扇区,加载到0x0:0x7c00
* 即BOOTSEG,并跳转到这里执行,然后程序会把自己搬运到0x:0x9000,如何搬?下面的* 代码很简单,不说了!为什么搬?最好的解释是,这块内存后面会挪作他用。
*/
*****************section1******************
movw $BOOTSEG, %ax
movw %ax, %ds
movw $INITSEG, %ax
movw %ax, %es
movw $256, %cx
subw %si, %si
subw %di, %di
cld
rep
movsw
****************section 1*******************
// 所谓的长跳转,后面跟段基址:段内偏移。别忘了这里是16位实模式
ljmp $INITSEG, $go
// 上面的ljmp的作用,就是在搬运完之后从go这里开始继续执行
go: movw $0x4000-12, %di // 用来设置栈底
// 注意在上面的搬运过程中ax被置为0x9000,即INITSEG
movw %ax, %ds
// 接下来这两句,将stack设置在0x9000:(0x4000 -12)
movw %ax, %ss
movw %di, %sp
movw %cx, %fs //开机上电,cx会被置为0,这里也就把fs置为0
movw $0x78, %bx // %fs:%bx,即0x0:0x78处放置这磁盘参数表地址
pushw %ds
// 将参数0x0:0x78处存放的两个word(共32 bits),依次放入到ds和si
// 所以ds:si就是磁盘参数表的首地址,这个表的总长度为12bytes
ldsw %fs:(%bx), %si #ds:si is source
// section 2的作用就是从ds:si赋值12bytes到es:di,es:di即0x9000:(0x4000-12)
// 也就是说在栈底之后的12bytes,放置了从原始位置搬运过来的磁盘参数表
*********section2***************
movb $6, %cl #copy 12 bytes
pushw %di #di = 0x4000-12.
rep # don't need cld-> done on line 66
movsw
*********section2***************
popw %di
popw %ds
movb $36, 0x4(%di) # patch sector count
// 重新设置0x0:0x78处的磁盘参数表的地址,这样以后在通过int 13查看参数表的
// 信息时,就到新的位置去了。
movw %di, %fs:(%bx)
movw %es, %fs:2(%bx)
load_setup:
xorb %ah, %ah #reset FDC
xorb %dl, %dl
int $0x13
// 调用bios int 13中断服务,从设备的第二个扇区开始复制总共4个扇区(setup.S)到//0x9000:0x200,具体int 13 读扇区的具体参数设置,可以查看相关资料
*************section 3***************
xorw %dx, %dx # drive 0, head 0
movb $0x02, %cl # sector 2, track 0
movw $0x0200, %bx # address = 512, in INITSEG
movb $0x02, %ah # service 2, "read sector(s)"
movb setup_sects, %al # (assume all on head 0, track 0)
int $0x13 # read it
*************section 3***************
jnc ok_load_setup # ok - continue
// 加载setup.S失败,ax中含有错误码。这里会打印一些信息,并作重试
pushw %ax #dump error code
call print_nl
movw %sp, %bp
call print_hex
popw %ax
jmp load_setup
ok_load_setup:
// ds:si执行用于获得磁道总扇区数的猜测值,为什么使用猜测值呢?原因是没有可以
/
/直接使用的bios调用来获取总的扇区数,无奈之下:能读到36个扇区,就认为是36个,//不行就尝试18,15等,都失败时,就是用9
movw $disksizes, %si # table of sizes to try
linux怎么读文件内容probe_loop:
lodsb // 将猜测值依次放到al中
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论