说明一下,这里省略了一些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中