写一个引导程序(boot loader)

环境

首先,你需要安装NASM汇编器和QEMU来模拟一个虚拟机。用QEMU很好,因为我们不用担心有时候不小心写了烂的OS代码而把硬件给搞坏了;) 。在win 10的wsl或Ubuntu上你可以用这个命令来安装它们(之前可以用sudo apt-get update更新一下软件源):

sudo apt-get install nasm qemu

在Mac上你可以使用homebrew:

brew install nasm

在win 10上,你还要安装X Server,这样QEMU就可以从WSL中打开一个窗口。

Hello World的Bootloader

我们将编写一个软盘引导加载程序,它不需要我们处理文件系统,这有助于使事情尽可能简单。

当你按下电源键时候,计算机从存储在主板上的闪存加载BIOS。BIOS对硬件进行初始化和自测试,然后将第一个512字节从媒体设备(即CDROM或软盘)加载到存储器中。如果最后两个字节等于0xAA55,那么BIOS将跳转到位置0x7C00,有效地将控制转移到引导加载程序。
此时CPU以16位模式运行,这意味着只有16位寄存器可用。此外,由于BIOS只加载前512个字节,这意味着我们的引导加载代码必须保持在该限制之下,否则我们将击中未初始化的内存!

让我们把Help World World打印到屏幕上。要做到这一点,我们将使用“TTY模式下的写入字符”BIOS中断调用和加载字符串字节指令LoBSB,将地址DS:SI中的字节加载到AL中。下面是:

bits 16 ; tell NASM this is 16 bit code
org 0x7c00 ; tell NASM to start outputting stuff at offset 0x7c00
boot:
    mov si,hello ; point si register to hello label memory location
    mov ah,0x0e ; 0x0e means 'Write Character in TTY mode'
.loop:
    lodsb
    or al,al ; is al == 0 ?
    jz halt  ; if (al == 0) jump to halt label
    int 0x10 ; runs BIOS interrupt 0x10 - Video Services
    jmp .loop
halt:
    cli ; clear interrupt flag
    hlt ; halt execution
hello: db "Hello world!",0

times 510 - ($-$$) db 0 ; pad remaining 510 bytes with zeroes
dw 0xaa55 ; magic bootloader magic - marks this 512 byte sector bootable!

你可以使用nasm来编译它(把它保存为boot1.asm

nasm -f bin boot1.asm -o boot1.bin

如果我们运行hexdump boot1.bin,我们可以看到NASM创建了一些代码,填充了一些零点,然后将最后两个字节设置为幻数。

0000000 10be b47c ac0e c008 0474 10cd f7eb f4fa
0000010 6548 6c6c 206f 6f77 6c72 2164 0000 0000
0000020 0000 0000 0000 0000 0000 0000 0000 0000
*
00001f0 0000 0000 0000 0000 0000 0000 0000 aa55
0000200

现在我们可以运行这个东西!你可以告诉QEMU使用qemu-system-x86_64 -fda boot1.bin引导软盘。在win 10上,你之前还应该设置环境变量SET DISPLAY=:0(这个其实是指定了X Server的地址)。
你应该得到这样的东西!

原文链接

你可能感兴趣的:(linux,bootloader)