我正在学习如何从 osdev 制作引导加载程序。我正在使用 NASM 来组装我的代码,并使用 x86 机器来运行我的引导加载程序。这是一段打印字符并进入无限循环的代码:
BITS 16
xor ax, ax
mov ah, 0x0E
mov al, 0x41
int 0x10
jmp $
times 510-($-$$) db 0x00
db 0x55
db 0xAA
我的问题是:当我注释“xor ax, ax”指令时,为什么代码不运行?正如您在上面的代码中看到的,ax 值被更改为存储中断参数,因此代码应该在没有 xor 指令的情况下运行...
补充说明:
我正在使用以下命令在 Xubuntu 下汇编代码: nasm -f bin -o main.bin main.asm
我使用以下命令将 512 字节的机器代码存储到笔式驱动器中: sudo dd if=main.bin of=/dev/sdb
我的电脑可以从随身碟启动
非常感谢。
最佳答案
理论上您不需要 BPB在写 MBR 时而不是 VBR 1,并且xor ax, ax
指令的存在不会影响启动。
你应该包含一个 xor bh, bh
然而(更多关于 Int 10/AH=0Eh )
遗憾的是这只是理论。
特别是对于 USB 设备,BPB 由某些固件隐式假定,包括完整的 FDC 描述符(具有有效的操作系统名称)。
非常感谢 Michael Petch强调这一点。
自引入UEFI实现,特别是处理 CSM (Compatibility Support Module) 的部分,即传统引导,编写完全支持的 MBR 变得很棘手。
固件有时会尝试自动检测要使用的启动模式,并且由于所有 UEFI 设备也是符合规范的旧设备,因此固件必须依靠一些怪癖来区分它们。
我的固件将设备检测为“旧版”,即使明确如此告知,仅至少其中一项为真时:
- MBR 分区表中有一个可引导的非空分区。
根本不检查 CHS 或 LBA 中的起始/结束地址。 - 第一条指令是
xor ax, ax
(形式为:33 C0
或31 C0
)。 这是因为大多数引导加载程序做的第一件事是通过 AX 将段寄存器设置为零。
可能还有其他“特征”,比如在第一个字节处跳转,但我还没有测试过它们(还)。
如果固件未能将设备检测为遗留设备并且它不是 UEFI 兼容设备,它将被跳过。
您可以使用 xor ax, ax
(在这种情况下我建议使用 db 33h, 0c0h
和文档注释)或添加一个虚拟分区条目,如下图。
BITS 16
ORG 7c00h ;Soon or later you'll need this
xor bh, bh
mov ah, 0x0E
mov al, 0x41
int 0x10
_loop:
hlt ;Be eco-friendly
jmp _loop
;Pad to the first PTE (Partition Table Entry), it is at 1beh
TIMES 01beh-($-$$) db 00h
dd 80h ;Bootable partition at CHS 0:0:0 (Which is illegal but not checked)
db 01h ;Non empty partition (Type 1 is MS-DOS 2.0 FAT)
;Pad to the end of the sector minus 2
TIMES 510-($-$$) db 00h
dw 0aa55h ;Signature
1 根据dd
命令的参数。
关于x86 - (NASM) (80x86) 引导加载程序需要 xor ax, ax,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39240353/