您的位置:首页 > Web前端 > React

ReactOS 系统中DOSMBR

2014-05-08 09:51 281 查看
.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位置开始执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  windows