1、bios如何启动引导分区
2、段寄存器以及寻址方式
bios如何启动引导分区
bios在mbr引导模式下,会读取第一个扇区,并检测该扇区是否为启动扇区。怎么检查第一个扇区是否是启动扇区,继续往下启动呢,X86规定死了,该扇区的结尾,要以55aa为结尾。再介绍一个知识点,硬盘是以扇区作为操作的,一个扇区是512个字节。因此,末尾以55aa为结尾,可以看作511号字节为55,512号字节为aa。当第一个扇区的代码段,不超过512字节的时候,要把剩余的直到509的字节位清0。当超过512字节时(请保证主引导扇区不超过512字节),如果超过,请从代码段中,将启动代码从硬盘中拷贝出来再执行,这个以后的blog会继续讲解。因此,不超过512字节时,一个合格的主引导扇区要这么写代码:times 510-($ - $$) db 0 db 0x55,0xaa。这里面 $- $ $分别代表了啥呢? $表示改该段主引导分区的汇编结束的地址。比如你的代码写了400字节,那么这个时候 $就代表了400,而 $ $代表了整个代码汇编开始的地址,在这儿汇编开始的地址就是0。因此510 - ( $ - $ $)就表示了510 - (400 - 0)= 110。times表示重复执行,因此这个代码表示填充110个0,从400到510,最后511字节为55,512字节为aa。这样子一个合格的主引导分区就完成了。
段寄存器和寻址方式
bios检测到主引导扇区是合格的时候时(以55aa为结尾),会将此代码加载到0x7c00处加载,下面由一套启动code为例。
mov ax,0xb800 ;指向文本模式的显示缓冲区
mov es,ax
;以下显示字符串"Label offset:"
mov byte [es:0x00],'L'
mov byte [es:0x01],0x07
mov byte [es:0x02],'a'
mov byte [es:0x03],0x07
mov byte [es:0x04],'b'
mov byte [es:0x05],0x07
mov byte [es:0x06],'e'
mov byte [es:0x07],0x07
mov byte [es:0x08],'l'
mov byte [es:0x09],0x07
mov byte [es:0x0a],' '
mov byte [es:0x0b],0x07
mov byte [es:0x0c],"o"
mov byte [es:0x0d],0x07
mov byte [es:0x0e],'f'
mov byte [es:0x0f],0x07
mov byte [es:0x10],'f'
mov byte [es:0x11],0x07
mov byte [es:0x12],'s'
mov byte [es:0x13],0x07
mov byte [es:0x14],'e'
mov byte [es:0x15],0x07
mov byte [es:0x16],'t'
mov byte [es:0x17],0x07
mov byte [es:0x18],':'
mov byte [es:0x19],0x07
infi: jmp near infi ;无限循环
times 510-($-$$) db 0
db 0x55,0xaa
可以看到此段代码在末尾以55aa结尾,因此该代码是一套启动代码。8086模式中,有许多的寄存器,例如ax、bx、cx、dx普通寄存器,也有cs、ds、es等段寄存器。86的寄存器都是16位的寄存器,但是86的寻址范围是20位的寻址范围,这导致了16位的寄存器没办法得到20位地址,这如何实现呢,就有了段寄存器的概念。将段寄存器和普通寄存器加在一起使用,得到20位的地址,将段寄存器中的地址左移4位,加上普通寄存器的值,就组成了20位的1MB寻址范围。例如上述代码中[es:0x00],由开头可知es = 0xb800,因此左移4位0xb8000,所以L的放在了0xb8000的位置,a放在了0xb8002的位置,这个位置是显卡显存的位置。显存上偶数位为字符位,而奇数位为颜色位。