gpt4 book ai didi

assembly - 引导加载程序在真实硬件上打印垃圾

转载 作者:行者123 更新时间:2023-12-04 18:35:54 24 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Custom bootloader booted via USB drive produces incorrect output on some computers

(2 个回答)


2年前关闭。




我正在尝试编写自己的 bootstrap 。虽然它在 QEMU、Bochs 和 VirtualBox 中运行良好,但我似乎无法让它在我的笔记本电脑上运行。

在我的笔记本电脑上,引导加载程序的行为与所有模拟器都大不相同,卡在看似随机的地方,拒绝打印,甚至跳过一些 jmp $指示。

虽然我在“真正的硬件”方面遇到了很多麻烦,但我认为所有这些问题都有一个原因。

以下代码是一个简短的引导加载程序,它应该打印 3 次“TEST”消息,然后通过跳转到同一位置挂起:

[BITS 16]                                                                          
[ORG 0x7C00]
jmp 0x0000:start_16 ; In case bootloader is at 0x07C0:0x0000
start_16:
xor ax, ax
mov ds, ax
mov es, ax
cli ; Disable interrupts
mov ss, ax
mov sp, 0x7C00
sti ; Enable interrupts
cld ; Clear Direction Flag
; Store the drive number
mov [drive_number], dl
; Print message(s)
mov si, msg
call print_string
mov si, msg
call print_string
mov si, msg
call print_string

jmp $ ; HALT

; print_string
; si = string
print_string:
pusha
mov ah, 0x0E
.repeat:
lodsb
cmp al, 0x00
je .done
int 0x10
jmp short .repeat
.done:
popa
ret

; Variables
drive_number db 0x00
msg db 'TEST', 0x0D, 0x0A, 0x00
times 510-($-$$) db 0x00
db 0x55
db 0xAA

编译和模拟代码:
$ nasm -f bin bootloader.asm
$ qemu-system-x86_64 bootloader

在模拟器上,它打印“TEST”三次并挂起,在我的笔记本电脑上,它打印“TEST”,然后是 3 个奇怪的字符:

Bootloader output on my laptop.

大多数引导加载程序代码来自 http://wiki.osdev.org也不起作用。例如,没有来自 http://wiki.osdev.org/Babystep2 的代码片段在我的笔记本电脑上工作。

我的代码有什么问题?我该如何解决?

附加信息

如果我删除 2 个不必要的 mov si, msg , 打印“TEST”消息 两次 .

笔记本电脑:
  • 华硕 Vivobook S200,
  • CPU:英特尔 i3-3217U
  • BIOS:美国大趋势,版本 210。
  • 计算机可以与任何其他引导加载程序(例如 Grub)配合使用。

  • 组装和写作:
    $ nasm -f bin bootloader.asm
    $ qemu-system-x86_64 bootloader # TEST 1
    $ sudo dd if=/dev/zero of=/dev/sdd bs=1M count=1 # clean the USB
    $ sudo dd if=bootloader of=/dev/sdd conv=fsync # write to USB
    $ qemu-system-x86_64 /dev/sdd # TEST 2

    编辑 1

    Ross Ridge 在评论中注意到 Ω♣|是引导加载程序的前 3 个字节。

    编辑 2

    更新打印函数和字符串:
    print_string:                                                                      
    pusha
    .repeat:
    mov ah, 0x0E
    xor bx, bx
    cld ; Clear Direction Flag
    lodsb
    cmp al, 0x00
    je .done
    int 0x10
    jmp short .repeat
    .done:
    popa
    ret

    msg db 'TEST', 0x00

    输出

    TEST .缺少另外两个。

    编辑 3

    正如罗斯·里奇 (Ross Ridge) 所建议的, dumpregs已添加以便更好地调试。 int 0x10 不是 修改任何寄存器。
    经过一些测试,我已经移动了 dumpregs周边功能 drive_number分配和 jmp $刚过。代码应该打印 1 行寄存器转储和暂停。相反,它继续:
    dumpregs around drive_number assignment

    完整代码:
    https://gist.github.com/anonymous/0ddc146f73ff3a13dd35

    编辑 4

    使用以下命令反汇编当前的引导加载程序:
    $ ndisasm -b16 bootload2 -o 0x7c00
    https://gist.github.com/anonymous/c9384fbec25513e3b815

    最佳答案

    现在看起来 BIOS 可能正在修改 BIOS parameter block它错误地假设是加载到内存中的引导扇区的一部分。它可能觉得它需要,因为它在引导时提供给 USB 设备的几何图形可能与引导扇区及其假定的 BPB 写入设备时使用的几何图形不同。由于在引导扇区开头存在跳转指令是应用程序测试 BPB 存在的方式之一,因此您可以尝试在引导扇区开头插入一些其他指令(但不是 NOP)。例如:

    [BITS 16]                                                                          
    [ORG 0x7C00]
    xor ax,ax
    jmp 0x0000:start_16 ; In case bootloader is at 0x07C0:0x0000
    start_16:

    请注意,远跳似乎不是 normal indicators of the presence of a BPB 之一。 .事实上,这是不存在 BPB 的确凿证据,因为 BPB 从偏移量 4 开始,并且远跳转指令长 5 个字节。

    如果这不起作用,您可以尝试为 BPB 保留空间,如下所示:
    [BITS 16]                                                                          
    [ORG 0x7C00]
    jmp start
    nop
    resb 8 + 25
    start:
    jmp 0x0000:start_16 ; In case bootloader is at 0x07C0:0x0000
    start_16:

    以下是一些可用于转储寄存器以帮助调试问题的代码:
    dumpregs:
    push es
    pusha
    push 0xb800
    pop es
    mov di, [vidmem_ptr]
    mov bp, sp
    mov cx, 8
    dump_loop:
    dec bp
    dec bp
    mov ax, [bp + 16]
    call printhex2
    inc di
    inc di
    loop dump_loop
    mov [vidmem_ptr], di
    popa
    pop es
    ret

    printhex2:
    push ax
    mov al, ah
    call convhex1
    pop ax
    convhex1:
    aam 16
    ; DB 0D4h, 16
    xchg al, ah
    call convhex
    mov al, ah
    convhex:
    cmp al, 10
    jb lessthan_10
    add al, 'A' - '0' - 10
    lessthan_10:
    add al, '0'
    stosb
    mov al, 7
    stosb
    ret

    vidmem_ptr dw 5 * 80 * 2 ; start at row 5

    它使用直接视频写入来转储所有通用寄存器。它使用 PUSHA/POPA 寄存器顺序:AX CX DX BX SP BP SI DI

    如果您将原始代码中的 INT 0x10 指令与调用此函数括起来,您应该得到如下输出:

    Screenshot of boot with debug output

    特别是您要确保左侧的 8 个数字与调试输出的每一行右侧的 8 个数字匹配。您使用的 BIOS 调用不应更改任何寄存器。

    关于assembly - 引导加载程序在真实硬件上打印垃圾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34966441/

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