繁体   English   中英

在程序集x86中加载旧的引导程序

[英]Loading old bootloader in assembly x86

我正在x86_64体系结构上的NASM x86中编写自己的引导程序,对于初学者来说,我只是想使用dd将现有的引导程序复制到第二个扇区,然后再复制回去并从程序集中运行。

文件.asm

org 0x7c00

jmp 0:start

start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x8000

mov           ah, 0x02
mov           al, 1
mov           dl, 0x80
mov           ch, 0
mov           dh, 0
mov           cl, 3
mov           bx, 0x7e00
int           0x13

jmp 0x7e00
times 510-($-$$) db 0
dw 0xaa55

times (1024 - ($ - $$)) db 0x00
third_sector:
mov           ah, 0x02
mov           al, 1
mov           dl, 0x80
mov           ch, 0
mov           dh, 0
mov           cl, 2
mov           bx, 0x7c00
int           0x13

jmp           0x7c00

该代码设置了堆栈,然后将其自身拍成0的1024个字节,以使代码的最后一位位于磁盘的第三扇区中,然后将磁盘中的第二个扇区加载到第一个扇区中,并跳到第一个扇区。

src.sh

#!/bin/bash
dd bs=1 count=512 if=/dev/c0d0 of=tmp
nasm -f bin file.asm -o file 
dd bs=1 count=1200 if=file of=/dev/c0d0
dd bs=1 count=512 seek=512 if=tmp of=/dev/c0d0

我正在做的是将原始引导加载程序复制到名为tmp的临时文件中,然后编译程序并将其放入旧的引导加载程序中(因为我在MINIX 3.3.0上工作,因此是/ dev / c0d0),然后将旧的引导加载程序移至第二扇区。

结果是“从硬盘引导”字符串,这很好,然后出现“ NetBSD MBR引导错误P”,它对应于“无netBSD分区”。

编辑:粘贴了错误的asm文件。 第二次编辑:错误已更改,但仍然存在。

我可以先将512B中的所有内容都塞满,但是随后阅读旧的引导加载程序后,我将无法再跳到开头

当然,您不能同时在7C00-7DFF区域中运行,也不能在其中加载其他扇区,因此,您需要准备一些将在7C00-7DFF外部运行的代码,它将原始引导扇区加载到预期为0000:7C00,并像BIOS一样执行它。

我试图修改您的代码以使其正常工作,但是我无法调试/验证其是否有效,因此请谨慎操作(我使用ndisasm来反汇编生成的二进制文件,并且一切正常,即,重定位的代码不依赖于在其地址上,因此您可以将其自由移动到任何内存,并且它应该将该扇区加载并执行到7C00。

只需确保您没有在该代码中添加任何内容,否则在重新定位到7e00之后会中断。

org 0x7c00

jmp 0:start

start:
mov ax, cs     ; ax = 0
mov ds, ax
mov es, ax
mov ss, ax
mov sp, ax     ; ss:sp = 0:0
; relocate second boot loader code outside of 7C00-7DFF (to 7E00)
mov si, boot_loader_code   ; address of code to relocate
mov di, 0x7e00             ; new address of code
mov cx, boot_loader_code_length
cld
rep movsb
; execute the relocated second boot loader
jmp 0x7e00

boot_loader_code:
    ; load second boot loader to 0:7c00 and execute it
    mov     ah, 0x02    ; load sector service
    mov     al, 1       ; load 1 sector
    ; mov     dl, 0x80    ; drive 0
    ; DL is set by BIOS originally
    ; and this code did/will not change it
    mov     ch, 0       ; track/cylinder
    mov     dh, 0       ; head number
    mov     cl, 3       ; sector number
    mov     bx, 0x7c00  ; es:bx pointer to buffer
    int     0x13        ; BIOS "load sector" service
    jmp     0:0x7c00
boot_loader_code_length EQU ($ - boot_loader_code)

    times   510-($-$$) db 0
    dw      0xaa55

仍然无法正常工作

好吧,如果没有调试器,您几乎无法在汇编器中进行编程,有太多的地方会出错,并且每个细节都可能很重要。 如果您有过asm的经验,可以将其退出,但是如果您正在学习,请获取一些PC模拟器,您还可以在其中调试诸如bochs之类的东西。 并首先使用文档(就像您的incbin注释一样,它在NASM文档中也进行了描述,以及它的确切作用)。

我通过Michael的注释对源代码进行了调整,但是我仍然没有办法对其进行验证/调试(太懒了,无法安装bochs +学习如何设置引导加载程序扇区),但是代码本身是“确定”的,它主要处理注释说。 这是否足以启动PC机,这是另一个问题。 它只是解决了您的代码中明显的问题,即试图使“第三”部分位于512B单扇区块之外。

NetBSD卷启动记录(由NetBSD称为分区启动记录或PBR)读取从其启动的磁盘的第一块,并检查其是否与自身相同。 如果不是,则假定磁盘具有MBR,并尝试在MBR中找到NetBSD引导分区。 它通过简单比较内存中加载的自身的前4个字节和磁盘上第一个扇区的前四个字节来进行此检查。

由于替换引导扇区的开头不是完全相同的4个字节,因此它被解释为带有分区表的MBR。 由于您的引导扇区实际上没有MBR分区表,因此NetBSD VBR无法找到NetBSD分区,因此会打印error P (取决于error no slice配置方式,可能是error no sliceerror no slice )。

要解决此问题,您需要将磁盘的分区表复制到替换MBR中。 注意这也是必要的,因为NetBSD本身(或您正在引导的任何东西)也将要读取分区表。

如果您的磁盘没有带有分区表的MBR,而是以NetBSD VBR(PBR)开头,则您无能为力,无法解决此问题。 在这种情况下,当NetBSD VBR正常启动时,它将前15个扇区以0000:1000的速度加载到内存中,如上所述,检查前四个字节是否与自身匹配,如果是,则跳转到以0000:1000加载的代码。 由于您要更改磁盘的前三个扇区,因此还将覆盖扇区2上的NetBSD磁盘标签,以及NetBSD在扇区3上称为阶段1引导程序(bootxx)的开始。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM