标签:
在存储介质(硬盘、软盘、光盘)中有一块特殊的区域,叫做引导区。在计算机启动后,BIOS会读取引导区内的代码到内存中去,然后将执行这些代码。引导区的位置和大小与计算机的平台有关,对于IBM-PC兼容机,引导区位于存储介质的第一个扇区,大小为512字节。位于引导区内的代码就称为引导程序。引导区内是否含有引导程序由引导区内的标记标识。对于IBM-PC兼容机,如果引导区内的最后两个字节为0x55,0xAA,则BIOS检测程序认为引导区内包含引导程序。引导程序并不一定要实现加载操作的功能,它可以是任何程序。
IBM-PC兼容机的具体启动过程如下:
1.按下计算机的电源键后,x86 CPU就开始在实模式下运行位于物理地址0xFFFFFFF0(通常这个地址是指向的是位于ROM中的BIOS的入口点)处的指令,这个指令是一个跳转指令,跳转到BIOS的启动程序。启动程序运行硬件检测和初始化操作。
2.在初始化所需要的硬件后,BIOS就依据设定的启动顺序遍历存储设备,直到找到一个可引导的设备。一个可引导的存储设备是引导区内包含引导程序。BIOS通过检查引导区的最后两个字节是否为0x55,0xAA来判断引导区内是否包含引导程序。
3.一旦BIOS找到了可引导的设备,它就加载引导区代码到内存物理地址的0x7C00(通常是Segment:Offset 0000h:7C00h,也有些BIOS为07C0h:0000h),之后BIOS将控制权交给引导程序,CPU开始执行引导程序,引导程序开始加载操作系统内核或者其他。
在格式化硬盘安装好Windows后,硬盘第一个扇区(引导区)包含MBR引导代码,BIOS在加载MBR代码后,MBR开始检查硬盘中是否存在活动分区(含引导程序的分区),如果存在活动分区,则加载位于那个分区的引导程序(通常称为VBR,与操作系统相关),然后执行它。VBR的主要功能是加载操作系统的内核。
了解了相关知识,我们如何编写一个打印Hello World的引导程序呢?
需要准备的工具:
文本编辑软件、MASM编译器(我采用的是VS2008自带的ML 9.0)、16位Link程序、VMWare、PE(用于格式化VMWare创建的虚拟磁盘)、NtExplorer
具体步骤:
1. 打开你习惯使用的文本编辑器,编写下面代码。因为BIOS会将我们的引导程序加载到内存地址的7C00h处,所以我们需要org指令设置我们代码指令的地址值。
;------------------------------------------------------------ .286 ; CPU type ;------------------------------------------------------------ .model TINY ; memory of model ;------------------------------------------------------------ ;----------------------- CODE SEGMENT ----------------------- .code org 07c00h ; for BootSector main: jmp short start ; go to main nop ;--------------------- Print a char on the screen ------------ PrintChar PROC mov ah, 0Eh ;Tell BIOS that we need to print one charater on screen. mov bh, 0h ;Page no. mov bl, 07h ;Text attribute 0x07 is lightgrey font on black background int 10h ;Call video interrupt ret PrintChar ENDP ;------------------- Print a String on the screen ------------- PrintStr PROC next_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 PrintChar ;Else print the character which is in AL register jmp next_character ;Fetch next character from string exit_function: ;End label ret PrintStr ENDP start: cli ; Clear interrupt flags mov ax,cs ; Setup segment registers mov ds,ax ; Make DS correct mov es,ax ; Make ES correct mov ss,ax ; Make SS correct mov bp,7c00h mov sp,7c00h ; Setup a stack sti helloString BYTE ‘Hello World!‘, 0 mov si, offset helloString call PrintStr ; Print the ‘Hello World!‘ string ret BYTE 510 - ($ - main) DUP(0) ; Fill the reminder of the first sector with zeros BYTE 55h, 0AAh ; Fill the last two bytes with 55h, 0AAh int the first sector END main ; End of program
标签:
原文地址:http://www.cnblogs.com/hualiu0/p/5743872.html