当电脑以磁盘启动时,BIOS会自动载入这个磁盘的第一个扇区(共512字节),即这个磁盘的0面0磁道1扇区。如果这个扇区是以0xAA55这个两字节的16进制数结束,即该扇区最后两位是0×55、0xAA(AA为高位,因此在后),那么BIOS就会认为它是一个引导扇区。0xAA55因此也称为引导标识(Boot Sector Signature),而磁盘的第一个扇区也称为引导扇区(Boot Sector)。
如果BIOS发现该引导扇区可引导,那么BIOS就会将控制权全部交给这个扇区的代码。也就是说从此BIOS撒手不管了,接下来的时就由这512字节的引导代码来做了。你可以认为BIOS唯一做的东西就是载入引导扇区(固定地都是载入到内存中的0000:7C00处),并判断最后的两字节是否0xAA55,如果是那么就将控制权交给这个扇区的代码。
详细内容见这里。
好了,下面来实践一下。在网上找到了很多代码,其中这个代码是最简短的一个,使用NASM来进行编译。
[BITS 16] ;Tells the assembler that its a 16 bit code
[ORG 0x7C00] ;Origin, tell the assembler that where the code will
;be in memory after it is been loadedMOV SI, HelloString ;Store string pointer to SI
CALL PrintString ;Call print string procedure
JMP $ ;Infinite loop, hang it here.PrintCharacter: ;Procedure to print character on screen
;Assume that ASCII value is in register AL
MOV AH, 0×0E ;Tell BIOS that we need to print one charater on screen.
MOV BH, 0×00 ;Page no.
MOV BL, 0×07 ;Text attribute 0×07 is lightgrey font on black backgroundINT 0×10 ;Call video interrupt
RET ;Return to calling procedurePrintString: ;Procedure to print string on screen
;Assume that string starting pointer is in register SInext_character: ;Lable to fetch next character from string
MOV AL, [SI] ;Get a byte from string and store in AL register
INC SI ;Increment SI pointer
OR AL, AL ;Check if value in AL is zero (end of string)
JZ exit_function ;If end then return
CALL PrintCharacter ;Else print the character which is in AL register
JMP next_character ;Fetch next character from string
exit_function: ;End label
RET ;Return from procedure;Data
HelloString db ‘Hello World’, 0 ;HelloWorld string ending with 0TIMES 510 – ($ – $$) db 0 ;Fill the rest of sector with 0
DW 0xAA55 ;Add boot signature at the end of bootloader
使用NASM编译成boot.bin,并写到磁盘(可千万不要写到自己的硬盘上哦,拿软盘做实验吧~)的第一扇区上就可以了。重启动系统并以该磁盘启动就行了。瞧,经典的Hello World!


