为什么我的引导程序不能在最近的笔记本电脑上工作?

时间:2019-05-12 23:32:23

标签: assembly qemu boot bootloader bios

我想从头开始做一个简单的引导程序。我希望它能够在最近的笔记本电脑上的USB上启动,这意味着它具有UEFI启动功能,但从理论上讲它支持传统启动。

因此,我编写了一些汇编代码,仅打印“ hello world”,并使用nasm -f bin boot.asm -o boot.com进行了编译。 然后,我用dd从二进制文件构建了软盘。 磁盘与qemu-system-x86_64配合良好。我使用dd if = boot.bin of // dev / sda将其传输到格式化为FAT32的usb棒的MBR。 但是,当使用我最近的计算机在其上启动时,usb不会显示在可启动设备中。

我试图: -在Qemu(使用qemu-system-x86_64 -hdb / dev / sda)上成功启动 -在具有Intel Pentium 4处理器的非常老旧的计算机上启动它,一切按预期进行。 -在BIOS选项中启用传统模式 -禁用安全启动 -在另一台计算机上启动它,在可启动设备中出现usb棒,但没有打印任何内容。

我在互联网上找到它,所以组装应该正确

;; A tiny, working bootloader for x86 PCs. Has a few subroutines
;; so it's slightly less useless than just printing "hello world".
;;
;; writeup here: http://joebergeron.io/posts/post_two.html
;;
;; Joe Bergeron, 2016.
;;
    bits 16

    mov ax, 07C0h
    mov ds, ax
    mov ax, 07E0h       ; 07E0h = (07C00h+200h)/10h, beginning of stack segment.
    mov ss, ax
    mov sp, 2000h       ; 8k of stack space.

    call clearscreen

    push 0000h
    call movecursor
    add sp, 2

    push msg
    call print
    add sp, 2

    cli
    hlt

clearscreen:
    push bp
    mov bp, sp
    pusha

    mov ah, 07h     ; tells BIOS to scroll down window
    mov al, 00h     ; clear entire window
        mov bh, 07h         ; white on black
    mov cx, 00h         ; specifies top left of screen as (0,0)
    mov dh, 18h     ; 18h = 24 rows of chars
    mov dl, 4fh     ; 4fh = 79 cols of chars
    int 10h         ; calls video interrupt

    popa
    mov sp, bp
    pop bp
    ret

movecursor:
    push bp
    mov bp, sp
    pusha

    mov dx, [bp+4]      ; get the argument from the stack. |bp| = 2, |arg| = 2
    mov ah, 02h         ; set cursor position
    mov bh, 00h     ; page 0 - doesn't matter, we're not using double-buffering
    int 10h

    popa
    mov sp, bp
    pop bp
    ret

print:
    push bp
    mov bp, sp
    pusha
    mov si, [bp+4]      ; grab the pointer to the data
    mov bh, 00h         ; page number, 0 again
    mov bl, 00h     ; foreground color, irrelevant - in text mode
    mov ah, 0Eh         ; print character to TTY
 .char:
    mov al, [si]        ; get the current char from our pointer position
    add si, 1       ; keep incrementing si until we see a null char
    or al, 0
    je .return          ; end if the string is done
    int 10h             ; print the character if we're not done
    jmp .char       ; keep looping
 .return:
    popa
    mov sp, bp
    pop bp
    ret


msg:    db "Oh boy do I sure love assembly!", 0

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

我希望能够在运行i7-8550U处理器并兼容UEFI / Legacy的最新计算机上引导USB。 目前,USB记忆棒未在可启动设备中显示。

编辑: 谢谢您的回复 ! 我试图通过添加以下代码来设置Bios参数块(BPB):


ORG 0
BITS 16

jmp near start

db "MYBOOT  "      
dw 512           
db 1                
dw 1          
db 2             
dw 512                    
dw 65535          
db 0xf8     
dw 20      
dw 63            
dw 16    
dd 0            
dd 0        
db 0x29  
dd 0xffff  
db 0         
db 0         
db "NO NAME    "
db "FAT32   "

start:
   blablabla (see above)

并且USB记忆棒现在显示在ubuntu桌面上(我注意到,如果我使用的不是“ jmp near start”(例如“ jmp short start”),它就会消失) 但是它仍然不想出现在我的BIOS引导菜单中。 我真的不知道为什么它现在不想看到它。 我有BIOS版本F.23,也许有一种特殊的方法可以使用此BIOS?

1 个答案:

答案 0 :(得分:1)

我无法在注释中添加此内容,如果有帮助,我将对其进行适当的修改。提供的代码实际上也可以解决该问题。这是基于几个月前在OSDev Forum discussion上发现的具有更新BIOS的类似情况。

您能尝试使用此方法编译和构建MBR并查看BIOS是否将该驱动器识别为可引导驱动器吗?如果您恰巧在分区媒体上启动,它包含一个自引用分区表。不确定您的BIOS正在模拟哪种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

此代码可能无法使驱动器可见,甚至无法引导和输出任何内容,但是结果可以帮助缩小问题空间。我的一部分认为,考虑到BIOS的反应方式,不仅可能存在BPB问题,而且还有很多问题。