zoukankan      html  css  js  c++  java
  • [reprint]如何编写引导程序 Hello World

    在存储介质(硬盘、软盘、光盘)中有一块特殊的区域,叫做引导区。在计算机启动后,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,也有些BIOS07C0h: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
    复制代码

      2. 假设第一步中的代码保存为BootLoader.asm,在BootLoader.asm的目录下按住Shift,点击鼠标右键,选择在此处打开命令行(Windows 7系统,其他系统请通过CD指令转到BootLoader.asm文件的目录)。键入下面命令:
                      ml /AT /omf /Fl /Fm /c BootLoader.asm
                      C:Irvinelink6.exe /T /NOD BootLoader.obj
      如果提示找不到ml,请添加其路径到环境变量(我的路径为C:Program FilesMicrosoft Visual Studio 9.0VCinml.exe)。执行完后,我们将得到BootLoader.com文件。

    编译链接BootLoader.asm

       3. 使用VMware创建一个虚拟机,并新建一块虚拟磁盘(大小1G,预先分配磁盘空间,存储为单文件格式)。将新建的虚拟磁盘格式化为NTFS格式(使用PE或者其他工具)。右击VMWare界面左边的我们新建的虚拟机,进入设置->选中我们新建的磁盘->工具->映射(或者也可以通过菜单的文件->映射虚拟磁盘->映射),出现下面的对话框。去掉read-only的选项,然后点击OK。

      4. 打开NtExplorer软件,先进入Tools->Options,将安全模式改为Virtual Write。然后点击菜单File->Drive,选择Z盘。按F3键,进入16进制编辑模式。可以看到扇区0已经有MBR代码了。

      将光标位于00位置处,然后选择菜单Edit->Paste from file,选择我们之前生成的BootLoader.com文件。然后选择Tools->Options,点击Write->OK。

      5. 再次选择我们新建的虚拟机,进入设置,取消磁盘的映射。然后点击启动虚拟机,你就可以看到Hello World了!

     

    相关资料:
      1. How to develop your own Boot Loader
      2. Writing Hello World Bootloader
      3. Boot sector

     

    作者: pzxbc
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    IDEA使用总结1-Github下载代码和上传代码到Git
    Mysql-安装指南
    Dubbo安装及其实战1
    分布式设计(学习内容目录--后端架构师)
    elasticsearch安装指导(new)
    浅谈TCP/IP(new 常见面试问题)
    浅谈常用的设计模式(new)
    浅谈Elasicsearch
    浅谈数据库分库分表(new)
    JAVA 电子书下载地址
  • 原文地址:https://www.cnblogs.com/hualiu0/p/5743872.html
Copyright © 2011-2022 走看看