我想从头开始做一个简单的引导程序。我希望它能够在最近的笔记本电脑上的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?
答案 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问题,而且还有很多问题。