ReactOS 系统中DOSMBR

前端之家收集整理的这篇文章主要介绍了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
    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位置开始执行。

猜你在找的React相关文章