前端之家收集整理的这篇文章主要介绍了
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和80H。80H为活动,00H为非活动。 |
开始柱面(Starting Cylinder)、开始磁头(Starting Head)、开始扇区(Starting Sector) |
结束柱面(Ending Cylinder)、结束磁头(Ending Head)、结束扇区(Ending Sector |
相对扇区数(Relative Sectors)从磁盘的开始到该分区开始的偏移量,可以看成是分区在硬盘中的起始地址。 |
总扇区数(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位置开始执行。
-
-
-
-