我正在尝试在nasm中构build一个简单的x86 Linux引导程序。
Linux bzImage从第一个扇区开始存储在磁盘分区sda1上。
我从bzImage(15个扇区)将实模式代码从0x7E00开始读入内存。 但是,当我跳进代码只是挂起,没有任何反应。
我已经在sda上创build了主引导logging的代码。 我可能是最好的,如果我只附加整个事情。 我想知道为什么它挂在远跳转指令后。
[BITS 16] %define BOOTSEG 0x7C0 %define BOOTADDR (BOOTSEG * 0x10) %define HDRSEG (BOOTSEG + 0x20) %define HDRADDR (HDRSEG * 0x10) %define KERNSEG (HDRSEG + 0x20) [ORG BOOTADDR] entry_section: cli jmp start start: ; Clear segments xor ax, ax mov ds, ax mov es, ax mov gs, ax mov fs, ax mov ss, ax mov sp, BOOTADDR ; Lots of room for it to grow down from here ; Read all 15 sectors of realmode code in the kernel mov ah, 0x42 mov si, dap mov dl, 0x80 int 0x13 jc bad ; Test magic number of kernel header mov eax, dword [HDRADDR + 0x202] cmp eax, 'HdrS' jne bad ; Test jump instruction is there mov al, byte [KERNSEG * 16] cmp al, 0xEB jne bad xor ax, ax ; Kernel entry code will set ds = ax xor bx, bx ; Will also set ss = dx jmp dword KERNSEG:0 ; Simple function to report an error and halt bad: mov al, "B" call putc jmp halt ; Param: char in al putc: mov ah, 0X0E mov bh, 0x0F xor bl, bl int 0x10 ret halt: hlt jmp halt ; Begin data section dap: ; Disk address packet db 0x10 ; Size of dap in bytes db 0 ; Unused dw 15 ; Number of sectors to read dw 0 ; Offset where to place data dw HDRSEG ; Segment where to place data dd 0x3F ; Low order of start addres in sectors dd 0 ; High order of start address in sectors ; End data section times 446-($-$$) db 0 ; Padding to make the MBR 512 bytes ; Hardcoded partition entries part_boot: dw 0x0180, 0x0001, 0xFE83, 0x3c3f, 0x003F, 0x0000, 0xF3BE, 0x000E part_sda2: dw 0x0000, 0x3D01, 0xFE83, 0xFFFF, 0xF3FD, 0x000E, 0x5AF0, 0x01B3 part_sda3: dw 0xFE00, 0xFFFF, 0xFE83, 0xFFFF, 0x4EED, 0x01C2, 0xb113, 0x001D part_sda4: dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 dw 0xAA55 ; Magic number at relative address 510 mbrend: ; Relative address 512
假设你的代码是一个引导程序(因此不是MBR):
puts("Read error while trying to load boot loader")
而不仅仅是putc('B')
)。 其他的东西(加载内核片段,设置视频模式,在“真实模式内核头”字段中设置正确的值等)应该在附加扇区中,而不是在第一个扇区中。 请注意,计算机启动的方式经过精心设计,任何MBR都可以加载任何磁盘上任何分区上的任何操作系统; 并且MBR可以是允许安装多个操作系统(例如,用户可以使用漂亮的菜单或某事来选择MBR的代码应该链接哪个分区)的更大的一部分(例如启动管理器)。 这种设计允许用户在任何时候用其他任何东西替换MBR(或引导管理器)而不影响任何安装的操作系统(或导致所有安装的操作系统需要修复)。 举一个简单的例子,一个用户应该能够拥有12个不同的分区,这些分区都包含你的启动加载器和一个独立/独立版本的Linux,然后安装任何启动管理器(例如GRUB,Plop,GAG,MasterBooter等)随时想要。
对于你的代码为什么挂起来,这不是很重要,因为所有的代码都需要重写。 如果你很好奇,我强烈建议在一个带有调试器的仿真器(例如Bochs)中运行它,这样你就可以精确地检查发生了什么事情(例如,在0x00007E00转储内存以查看它包含的内容,单步执行JMP看看正在执行什么等)。
评论不符合代码!
xor bx, bx ; Will also set ss = dx
我严重怀疑这是否是你的问题…
免责声明:我没有这样做! 我是“鸡”,一直用软盘启动我的bootin。
在MBR中我所期望的是让它自行移动,然后再将活动分区上的第一个扇区加载到7C00h,然后跳到那里。 这个“真正的引导程序”加载其余的。 我不熟悉bzImage的布局 – 也许它会在7E00h加载…
我想我已经过了头了。 我会给我外套…