ReactOS 系统中DOSMBR


.code16
real_start:
    cli
    cld
    xor ax, ax
    mov ss, ax          
    mov ds, ax
    mov bp, HEX(7c00)
    lea sp, [bp-32]
    sti
    mov ax, HEX(1FE0)
    mov es, ax
    mov si, bp
    mov di, bp
    mov cx, 256
    rep movsw
首先将整个数据从1FE0:7C00处给复制到0:7C00处;然后对复制过去的数据进行验证。
    ljmp16 HEX(1FE0), cont
cont:
    mov ds, ax
    mov ss, ax
    xor ax, ax
    mov es, ax
    lea di, [bp + HEX(1be)] // start of partition table
test_next_for_active:
    test byte ptr ds:[di], HEX(80)
    jne active_partition_found
    add di, 16                    // next table
    cmp di, HEX(07c00) + HEX(1fe) // scanned beyond end of table ??
    jb test_next_for_active
首先,跳转的时候会将CS给设置为1FE0。然后设置其他的段寄存器,注意上面的DS没有设置成1FE0,所以是复制到0:7C00,然后找到活动的主目录。
    call print
    .asciz "no active partition found"

WAIT_FOR_REBOOT:
    jmp WAIT_FOR_REBOOT
trouble_reading_drive:
    call print
    .asciz "read error while reading drive"
    jmp WAIT_FOR_REBOOT

invalid_partition_code:
    call print
    .asciz "partition signature != 55AA"

    jmp WAIT_FOR_REBOOT

active_partition_found:
    call read_boot_sector
   jc  trouble_reading_drive 

如果没有找到却推出循环,那么就要打印出“no activate partition found"字符串,下面先看看这个打印函数,这个函数的实现很有趣,很类似于C语言的函数调用。

print_1char:
    xor bx, bx                   // video page 0
    mov ah, HEX(0E)              // else print it
    int HEX(10)                  // via TTY mode
print:
    pop si                       // this is the first character
print1:
    lodsb                        // get token
    push si                      // stack up potential return address
    cmp al, 0                    // end of string?
    jne print_1char              // until done
    ret                          // and jump to it
首先,执行的第一条语句是pop si,然后由将si当中的额字符经过lodsb指令传递给al,这里由于si指向整个字符串,这些字符串由伪指令.asciz放入到堆栈当中,同时这里也是需要执行的下一条指令,所以需要压栈,以便于后面的ret执行。如果需要打印消息了,就死循环等待用户按下开机重启键。而如果找到相应的活动分区,就执行读MBR操作。

read_boot_sector:
    mov bx, HEX(55aa)
    mov ah, HEX(41)
    int HEX(13)//利用系统中断对参数进行再一次验证,如果置进位并且BX不等于AA55,则表明返回错误
    jc  StandardBios    //  
    cmp bx, HEX(0aa55)  //    
    jne StandardBios
    test cl, 1         //如果CX的最低位为1,表明使用包结构访问数据,否则返回错误
    jz StandardBios
    jmp short LBABios
_bios_LBA_address_packet:
    .byte 16
    .byte 0
    .byte 4         // read four sectors - why not
    .byte 0
    .word HEX(7c00) // fixed boot address for DOS sector
    .word HEX(0000)

_bios_LBA_low:
    .word 0
_bios_LBA_high:
    .word 0
    .word 0,0
LBABios:
	mov ax, [di + 8]
	mov word ptr ds:[_bios_LBA_low], ax
	mov ax,[di + 8 + 2]
	mov word ptr ds:[_bios_LBA_high], ax

       mov ax, HEX(4200)    //  regs.a.x = LBA_READ;
       mov si, offset _bios_LBA_address_packet // regs.si = FP_OFF(&dap);

       int HEX(13)
       ret

INT13 AH=42用于读取磁盘的数据,调用的时候需要传入三个参数,AH=42表明调用函数的序号,DL表示磁盘驱动的序号,在这里整个DL一直没有改变,所以是在读取硬盘分区表的时候就存在的,DS:SI在上面的函数当中进行设置.首先通过两条mov指令设置_bios_LBA_high和_bios_LBA_low,然后在后面将_bios_LBA_address_packet 的偏移放到SI当中。其中整个SI所指向的地址的数据要求如下:

00h

1 byte

整个数据区域的大小,为16

01h

1 byte

未用,必须为0

02h..03h

2 bytes

需要读取多少个扇区,这里是4

04h..07h

4 bytes

整个扇区将被读入内存的偏移地址

08h..0Fh

8 bytes

从哪里开始读,这八个字节由上面的mov指令实现

硬盘分区表的结构

字节偏移

字段名及说明

00

活动分区标志,只能是00H和80H。80H为活动,00H为非活动。

01 - 03

开始柱面(Starting Cylinder)、开始磁头(Starting Head)、开始扇区(Starting Sector)

04

分区的类型

05 - 07

结束柱面(Ending Cylinder)、结束磁头(Ending Head)、结束扇区(Ending Sector

08 – 0B

相对扇区数(Relative Sectors)从磁盘的开始到该分区开始的偏移量,可以看成是分区在硬盘中的起始地址。

0C – 0F

总扇区数(Total Sectors)为该分区的扇区总数。通过4个字节可以表示2^32个扇区。

通过上面两个表可以很容易那两句mov指令了,之所以需要两句mov,是因为现在系统还在16位模式下面。读取到完整的数据到内存当中之后,下面就验证一下,然后跳转到内存地址开始执行。上面的LBABios最后的ret返回语句将直接返回到call read_boot_sector后面。而进位标志则由LBABios中的int 13设置或者清空。如果设置了进位标志表明读取出错,反之读取正确。
cmp word ptr es:[HEX(7c00)+HEX(1fe)], HEX(0aa55)
    jne invalid_partition_code
    ljmp16 0, HEX(7c00)            

在进行简单地比较之后,就直接跳转到7C00位置开始执行。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值