Yanyg - SAN Software Engineer

深入理解 GNU GRUB - 02 boot.S 2.5 MBR过程模拟实现

目录

1 MBR过程模拟实现

现在,我们对系统引导的第一步已经有了一个详细的认识。为了更深一步的理解MBR和这些 BIOS调用,提供一些测试题目:

  • 开机后在屏幕上输出”Hello cppgp”,并在一定时间后重复输出;
  • 开机后紧跟着读取第二个扇区,并且显示整个扇区512字节到屏幕上。

实现上述功能,编译生成512字节的IMG文件,设置虚拟机通过软盘引导,选择使用软盘镜像文件,设置镜像文件为我们编译生成的IMG文件,就可进行测试。下文首先简单介绍虚拟机配置,然后实现上述的1) 、2)两个题目。

1.1 测试虚拟机配置

最新注释:Debian下安装 qemu-system-x86即可:

~$ sudo apt-get install qemu-system-x86

《自己动手写操作系统》第二章“搭建你的工作环境”,对虚拟机选择、工作平台搭建、测试引导程序等都有详细的描述。这里只简单介绍搭建Vmware Work Station V7.1.3测试虚拟机的过程(其他版本的Vmware Workstation类似)。如下: 1). 选择菜单”File”->”New”->”Virtual Machine”创建一个新的虚拟机。在安装向导的帮助下可以简单完成。其中主要的选择如下:配置选择”Custom(advanced)”,硬件兼容版本选择” Workstation 6.5-7.x”操作系统安装选择”I will install the operating system later”,客户操作系统选择”Linux”,虚拟机名称为”grub-analysis”并定制你的保存路径,处理器配置默认,内存配置默认,网络连接默认,IO控制器类别默认,选择磁盘选择”Create a new virtual disk”,磁盘类型默认,磁盘大小默认(我们不会用到的),磁盘名称默认,单击”Finish”完成。 2). 选中刚才创建的虚拟机,右键选择”Settings”,选择软盘”Floppy”,”Device Status”选择”Connect at power on”。”Connection”选择”Use floppy image file”,选择”Browse”确保选择自己生成的IMG文件。 3). 选择菜单”Vm”->”Power”->”Power On to BIOS”,在Boot配置项中选择确保有软盘驱动器且是第一引导选择。默认配置便是这样,一般不用更改。 4). 启动虚拟机,就会使用设定的IMG文件引导。

1.2 TODO "Hello cppgp"的实现

/*
 * boot-hello-cppgp.S
 */
        .file "boot-hello-cppgp.S"
        .text
        .code16
.globl _start
_start:
        jmp after_pb
output:
        .asciz "Hello Cppgp/r/n"
idle_repeat:
        .long 0xA0000000
after_pb:
        cli
        /*
         * some bogus BIOS will jump to CS:IP=0x7C00:0000
         * instead of CS:IP=0x0000:0x7C00
         */
        ljmp $0, $real_start
real_start:
        xorw %ax, %ax
        movw %ax, %ds
        movw %ax, %ss
        movw $0x200, %sp
        sti
        /* do output and change color forever */
loop_output:
        movw $output, %si
        call message
        /* waiting for repeating idle */
        xorl %eax, %eax
loop_idle:
        incl %eax
        cmpl idle_repeat, %eax
        jne loop_idle
        jmp loop_output
/* message function */
1:
        movb $0xE, %ah
        int $0x10
message:
        lodsb
        cmpb $0, %al
        jne 1b
        ret
. = _start + 0x1FE
magic:
        .byte 0x55, 0xAA

在Linux下使用GCC编译、连接,使用objcopy提取IMG。如下:

~$ gcc -Wall -W -nostdinc -fno-builtin -m32 -MD -c -o boot-hello-cppgp.o boot-hello-cppgp.S
~$ gcc -o boot-hello-cppgp.exec boot-hello-cppgp.o -m32 -Wl,--build-id=none -m32 -nostdlib -Wl,-N  -Wl,-Ttext,0x7C00
~$ objcopy -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn boot-hello-cppgp.exec boot-hello-cppgp.img

1.3 测试

~$ qemu-system-x86_64 boot-hello-cppgp.img

不依赖任何操作系统,可以看到屏幕显示:

Sea BIOS (version...)

iPXE ...

Booting from Hard Disk...
Hello cppgp
Hello cppgp
_