gpt4 book ai didi

macos - 引导加载程序的问题

转载 作者:行者123 更新时间:2023-12-01 07:50:13 24 4
gpt4 key购买 nike

我正在学习Assembly,因此尝试编写自己的Bootloader。它可以在VirtualBox上正常工作,但不能在实际的PC上工作。
在电脑上“Hello World!”没有打印。

这是代码的用法:

BITS 16
ORG 0x7C00

jmp boot_sector

;------------------------------

OEMLabel db "FLOPPYDR"
BytesPerSector dw 512
SectorsPerCluster db 1
ReservedForBoot dw 1
NumberOfFats db 2
RootDirEntries dw 224
LogicalSectors dw 2880
MediumByte db 0xF0
SectorsPerFat dw 9
SectorsPerTrack dw 18
Sides dw 2
HiddenSectors dd 0
LargeSectors dd 0
DriveNo dw 0
Signature db 41
VolumeID dd 0x00
VolumeLabel db "FLOPPYDRIVE"
FileSystem db "FAT12"

;##############################
boot_sector:
;##############################

mov ax, 0x0000 ; Set up the stack
mov ss, ax ; Is this done correctly?
mov sp, 0x7C00 ; (I dont quite understand)

int 0x10 ; Set video mode

int 0x13 ; Reset the drive

mov ah, 0x02 ; Read more sectors
mov al, 2 ; Read two extra sectors,
mov bx, main_sector ; starting from the second.
mov ch, 0 ;
mov cl, 2 ; dl has been set already (?)
mov dh, 0 ;
int 0x13 ;

mov [bootdev], dl ; Store original dl in bootdev

jmp main_sector ; Go to the main sector (0x200 I think)

times 510 - ($ - $$) db 0 ; Fill in the rest of the sector with 0s
dw 0xAA55 ; and 0xAA55 at the end for signature

;##############################
main_sector:
;##############################

jmp Start

;------------------------------

bootdev db 0
msg db 'Hello World!', 10, 13, 0

;------------------------------

print_string:
mov ah, 0x0E
mov bh, 0
cmp al, 0
jne .loop
mov bl, 0x0F
.loop:
lodsb
cmp al, 0
je .end
int 0x10
jmp .loop
.end:
ret

;------------------------------

Start:
mov si, msg
call print_string
hlt

times 512 - ($ - main_sector) db 0

我也评论了一些问题,但这不是我的主要问题(嗯,也许我不知道答案会导致问题)。为什么在真正的PC上不起作用?

要编译,我使用 nasm -f bin boot.asm -o boot.bin并创建一个虚拟软盘文件,我使用 mkfile 1474560 floppy.flp
然后,我使用HexEdit打开 floppy.flp并将前64行(0x00-0x3F)替换为 boot.bin文件的内容(使用HexEdit打开)。
E9 38 00 46 4C 4F 50 50 59 44 52 00 02 01 01 00
02 E0 00 40 0B F0 09 00 12 00 02 00 00 00 00 00
00 00 00 00 00 00 29 00 00 00 00 46 4C 4F 50 50
59 44 52 49 56 45 46 41 54 31 32 B8 00 00 8E D0
BC 00 7C CD 10 CD 13 B4 02 B0 02 BB 00 7E B5 00
B1 02 B6 00 CD 13 88 16 03 7E E9 A3 01 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA <-- End of first sector
E9 24 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 21
0A 0D 00 B4 0E B7 00 3C 00 75 02 B3 0F AC 3C 00
74 04 CD 10 EB F7 C3 BE 04 7E E8 E6 FF F4 00 00 (The rest is just 0's).

当我将 floppy.flp刻录到USB驱动器时,这是终端:
Last login: Wed Sep 23 12:10:48 on ttys000
MacBook-Air:~ sasha$ cd ~/Desktop
MacBook-Air:Desktop sasha$ diskutil list
/dev/disk0
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *121.3 GB disk0
1: Apple_HFS 209.7 MB disk0s1
2: Apple_CoreStorage 120.5 GB disk0s2
3: Apple_Boot Recovery HD 650.0 MB disk0s3
/dev/disk1
#: TYPE NAME SIZE IDENTIFIER
0: Apple_HFS Macintosh HD *120.1 GB disk1
Logical Volume on disk0s2
8CD6A846-395D-4C97-A5DE-0A7ABA9F1C99
Unencrypted
/dev/disk2
#: TYPE NAME SIZE IDENTIFIER
0: Apple_partition_scheme *17.1 MB disk2
1: Apple_partition_map 32.3 KB disk2s1
2: Apple_HFS Flash Player 17.1 MB disk2s2
/dev/disk3
#: TYPE NAME SIZE IDENTIFIER
0: FLOPPYDRIVE *1.0 GB disk3
MacBook-Air:Desktop sasha$ diskutil unmountdisk /dev/disk3
Unmount of all volumes on disk3 was successful
MacBook-Air:Desktop sasha$ sudo dd bs=512 if=floppy.flp of=/dev/disk3
Password:
2880+0 records in
2880+0 records out
1474560 bytes transferred in 0.843982 secs (1747146 bytes/sec)
MacBook-Air:Desktop sasha$

最佳答案

我最近在Stackoverflow上对引导加载程序有了written的详细介绍。大多数涉及在一个模拟器或VM上但不在另一个模拟器(或物理硬件)上运行的情况的问题通常归结为当BIOS跳转到您的代码时对段寄存器的状态做出了错误的假设。在某些仿真器下,段寄存器中可能包含更多理智的值,但通常并非如此。从我之前的回答中,我发现了以下两个适用于此的技巧:

  • 当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的DS,ES,SS,SP寄存器。引导加载程序启动时,应适当设置它们。
  • 可以设置或清除lodsbmovsb等使用的方向标志。如果方向标志设置不正确,则SI / DI寄存器的方向可能会调整错误。使用STD / CLD将其设置为所需的方向(CLD =前进/ STD =后退)。在这种情况下,代码假定向前移动,因此应使用CLD。有关更多信息,请参见instruction set reference

  • 您的汇编代码被设置为假设起始点为0x7C00进行编译和链接(通过 ORG 0x7C00)。访问msg和bootdev之类的变量的代码将假定它们的内存地址在网段(DS)中是绝对的。这意味着,如果您的DS段无效,则可能在错误的位置寻址变量,数据和标签。举个例子:
    mov [bootdev], dl 

    具有对DS的隐式引用,并等效于使用显式DS段对其进行寻址:
    mov [ds:bootdev], dl

    如果DS中包含一些随机值,那么您很可能会在意想不到的地方访问内存。在某些环境中,DS可能仅为零,因此您的代码可以使用。

    您如何知道要使用哪个细分市场? BIOS会将引导加载程序加载到物理内存0x0000:0x7C00(segment:offset)处。您的原点(使用 ORG指令设置)与偏移量匹配,因此在您的情况下,DS应该设置为零。

    在您的代码中,ES也应设置为零。原因是 INT 0x13 AH=0x02(读取磁盘)说:

    ES:BX缓冲区地址指针

    想象一下,如果将ES设置为随机垃圾,那么读取的磁盘可能会读入您不想要的内存中。因此,就像DS一样,也必须设置ES。您已将Bootloader和内核写在起始点为0x7C00的同一文件中,因此再次需要使用设置为零的ES段。

    设置堆栈时,可以适当地设置ES和DS。
    mov ax, 0x0000            ; Set up the stack
    mov ss, ax ; Is this done correctly?
    mov sp, 0x7C00 ; (I dont quite understand)
    mov ds, ax ; Set DS to 0 because that is what your code needs
    mov es, ax ; ES the same as DS.
    cld ; Read my tip #2

    您确实询问过是否正确设置了堆栈。没有什么问题。您的指令有效地设置了一个堆栈,该堆栈从 0x0000:0x7C00向下延伸,位于刚好由引导加载程序占用的区域下方。剩下约27kb( 0x7C00-0x1000)的堆栈空间。 4k足以应付BIOS调用和您当前的代码。内存的第一个 0x1000通常用于中断表/ BIOS数据区等。

    我在您的代码中注意到的另一个错误是当您尝试重置磁盘驱动器时:
    int 0x10                  ; Set video mode
    int 0x13 ; Reset the drive

    您将AX设置为这两行上方的零。 INT 0x10 AH=0x00(设置视频模式)具有在AX中返回信息的副作用。由于可以破坏AX,因此您对 INT 0x13 AH=0x00的调用可能是错误的。在调用 int 0x13重置驱动器之前,您需要清除AH(或所有AX)。该代码应如下所示:
    int 0x10                  ; Set video mode
    xor ax,ax ; clear AX (AH=0)
    int 0x13 ; Reset the drive

    程序顶部有一个小问题,仅当您将此引导加载程序放在格式正确的FAT12磁盘映像上并尝试将其安装在操作系统中时,才可能出现问题。你有:
    jmp boot_sector
    ;------------------------------
    OEMLabel db "FLOPPYDR"

    引导加载程序中的磁盘结构应从第4个字节开始具有 OEMLabel。 NASM可以将 jmp boot_sector编码为2或3字节指令。使用 short强制执行2字节编码,后跟 NOP(1字节指令)。这会将 OEMLabel放在文件的第4个字节中。它可能看起来像这样:
    jmp short boot_sector
    nop
    ;------------------------------
    OEMLabel db "FLOPPYDR"

    或者,您可以编码一个 JMP,编码时可以是2个字节或3个字节,并在必要时使用NASM的 NOP指令用 TIMES填充它,以便 OEMLabel始终从第4个字节开始:
    jmp boot_sector
    times 3-($-$$) nop
    ;------------------------------
    OEMLabel db "FLOPPYDR"

    避免使用 hexedit在磁盘映像的开头手动插入引导程序代码的技巧是使用 dd。您可以使用 dd覆盖前1024个字节,并保持其余部分不变。尝试 dd if=boot.bin of=floppy.flp bs=512 count=2 conv=notrunc。这应该打开floppy.flp写入2512字节的扇区,其中包含来自boot.bin的1024字节,而不会截断文件(conv = notrunc)

    关于macos - 引导加载程序的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32738185/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com