我想学习汇编程序,以使用极小的裸代码来使任何x86兼容机器运行,以便在开机时在屏幕上显示硬编码文本。 我关心与x86 / IBM机器的完全兼容性。
我遵循了有关简单启动代码的教程,但惨遭失败,无法从笔记本电脑上的USB物理运行它们。就像我的笔记本甚至没有触摸MBR代码一样。 我花了两个星期阅读大量文章,这使我无所适从。我了解了有关BIOS参数块,分区条目,this old Phoenix BIOS specification和UEFI的许多知识。
我的笔记本计算机可以通过可引导的FreeDOS USB正常启动。 这是带MBR的FreeDOS USB的第一个扇区: Nice and full of real useful codey-code
我尝试从具有UEFI的台式计算机启动它,并且它可以正常工作。 我试图从装有Phoenix BIOS的笔记本电脑启动它,然后它起作用了。
然后我擦除了所有引导说明: Nice and full of NOTHING but one partition entry
我尝试从具有UEFI的同一台台式机启动它,但按预期失败。 我试图从装有Phoenix BIOS的笔记本电脑上启动它,并且它可以正常工作。我发誓。
我想知道为什么会有BIOS自行处理事务并跳过MBR指令,如果还有更多类似的信息,我在哪里可以找到它们的文档,以便使引导代码与所有BIOS完全兼容
笔记本电脑的BIOS版本为1.08,其EC版本为1.07。 我不想更新它。如果FreeDOS可以正常启动,那么我也希望我的启动代码也可以正常启动。
答案 0 :(得分:1)
此答案基于经验和有根据的猜测。如果没有实际的硬件,很难进行测试。我假设OP正在将其引导扇区写入MBR,而不是VBR。
多年来,BIOS的创建既愚蠢又聪明(有些太聪明了,恕我直言)。有些人试图根据存在的BIOS参数块和/或具有可引导分区的分区表来区分是软盘驱动器还是硬盘驱动器的介质。不幸的是,这不是标准化的,许多BIOS制造商仅针对Windows分区的磁盘测试其代码。
某些认为自己看到有效分区表的BIOS将进行HDD仿真,并尝试从活动分区加载卷引导记录(VBR),而不是在MBR上执行代码。我怀疑这是机器上的情况,尽管将代码清零并保留了分区表,但机器似乎仍然可以启动。执行的代码可能直接来自VBR。
如果使用充当硬盘驱动器(而非软盘)的设备,则可以创建带有分区表的MBR,其中唯一的活动分区从驱动器的开头开始(CHS = 0、0、1或LBA = 0) );标记为可引导;并且具有非零的分区类型。如果您遇到了直接加载VBR的机器意图,则此方法将诱使它将MBR加载为VBR。
应该在您要测试的计算机上以HDD介质的形式在USB上引导的示例代码如下所示:
bits 16
org 0x7c00
boot_start:
xor ax, ax ; DS=0 since we use ORG 0x7c00. 0x0000<<4+0x7c00=0x7c00
mov ds, ax
mov es, ax
; If you will be reading data into memory outside of 0x7c00 to 0x7dff
; then you want to set the stack SS:SP - uncomment these lines
; mov ss, ax ; Stack at 0x0000:0x7c00
; mov sp, 0x7c00 ; Just below bootloader
cld ; Forward movement of string instructions
; (MOVSB, SCASB, etc)
mov si, HelloWorldMsg ; Print hello world
call print_string
end_loop: ; Loop forever to terminate
hlt
jmp end_loop
; Function: print_string
; Display a string to the console on display page 0
;
; Inputs: SI = Offset of address to print
; Clobbers: AX, BX, SI
print_string:
mov ah, 0x0e ; BIOS tty Print
xor bx, bx ; Set display page to 0 (BL)
jmp .getch
.repeat:
int 0x10 ; print character
.getch:
lodsb ; Get character from string
test al,al ; Have we reached end of string?
jnz .repeat ; if not process next character
.end:
ret
HelloWorldMsg: db "Hello, world!", 0x0d, 0x0a, 0
times 446-($-$$) db 0 ; Pad with 0s up until first partition entry
part1_entry:
db 0x80 ; 0x80 = Active boot partition, 0x00=inactive
db 0x00, 0x01, 0x00 ; CHS of first absolute sector (MBR) of hard drive
; Head=0, Sector=1, Cylinder=0
db 0x0c ; Partition type (has to be non-zero)
; 0x0c = Win 95 FAT32 (LBA)
db 0x00, 0x01, 0x00 ; CHS of last absolute sector (MBR) of hard drive
; Head=0, Sector=1, Cylinder=0
; We are effectively saying Size of partition is 1 sector
dd 0x0 ; LBA of first absolute sector (0=MBR)
dd 0x1 ; Number of sectors in partition. We set it to 1 but if you
; wish you could set it to the number of sectors on the disk
times 510-($-$$) db 0 ; Pad remainder of boot sector up to boot signature. This zeroes
; partition entries 2,3,4 effectively making them inactive
dw 0xAA55 ; The standard PC boot signature after partition table
您可以使用以下方法构建MBR:
nasm -f bin boot.asm -o boot.bin
如果成功放置在介质上,则应打印此代码:
你好,世界!