gpt4 book ai didi

x86 - int 13h 42h 在 Bochs 中不加载任何东西

转载 作者:行者123 更新时间:2023-12-01 14:36:59 26 4
gpt4 key购买 nike

我将引导加载程序从 CHS 更改为 LBA,因此我替换了 int 13h 02hint 13h 42h .它在 QEMU 中正常工作,但是,我在使用 Bochs 和我的笔记本电脑运行它时遇到了麻烦。

我用 dd if=main.bin of=/dev/sdb bs=512 将引导加载程序写入 USB 闪存驱动器.笔记本电脑加载英特尔 UNDI 并给我以下错误:No bootable device - insert boot disk and press any key .

所以我尝试用 Bochs 调试它并注意到 Bochs 将这个二进制文件识别为可引导的。但是,在 int 13h 之后没有加载任何内容执行。

然后我尝试从这个闪存驱动器加载我的旧电脑,它工作正常!它加载程序并正确执行它。 QEMU 给了我同样的结果。

这是引导加载程序代码:

org 0x7c00
bits 16

boot:
cli
; Overlap CS and DS
mov ax, cs
mov ds, ax
mov es, ax
; Setup 4K stack before this bootloader
mov ax, 0x07c0
mov ss, ax
mov sp, 4096
; Load next sectors
mov si, DAP
mov ah, 42h
; DL didn't changed
int 13h
; Start
jmp bootend

; Disk address packet
DAP:
db 10h, 0
dw %1 ; Number of sectors to be loaded
dd bootend
dq 1

; Fill the rest of bootsector with zeroes and end it
times 510 - ($ - boot) db 0
dw 0xAA55
bootend:

bochsrc:
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xfffe0000
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
floppya: 1_44=main.bin, status=inserted
boot: a
panic: action=ask
log: bochsout.txt
mouse: enabled=0
keyboard: type=mf, serial_delay=200, paste_delay=100000
display_library: x, options="gui_debug"

最佳答案

LBA 磁盘访问可用性

并非所有 BIOS 都支持扩展的磁盘读写功能(尽管在现代硬件上它们几乎都支持)。并非所有 BIOS 都支持通过 Int 13h/AH=42h 对软盘进行扩展磁盘读取. BOCHS 也是如此。您可以通过 Int 13/AH=41h/BX=55AAh 测试驱动器上是否可以使用扩展磁盘功能。 .这会进行扩展磁盘安装检查。

如果您想使用扩展磁盘读取和 LBA 在 BOCHS 上测试您的代码,您将必须创建一个硬盘镜像并修改 BOCHS 以从它而不是软盘启动。 BOCHS 支持的最小硬盘镜像大小为 CHS = 1/16/63 即 512*16*63 = 516096 字节或 1008 个扇区,每个扇区 512 字节。

您可以修改您的 bochsrc.txt成为:

megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xfffe0000
vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest
boot: c
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=disk, path="disk.img", mode=flat, cylinders=0, heads=0, spt=0, model="Generic 1234", biosdetect=auto, translation=auto
panic: action=ask
log: bochsout.txt
mouse: enabled=0
keyboard: type=mf, serial_delay=200, paste_delay=100000
display_library: x, options="gui_debug"

我使用名为 disk.img 的磁盘镜像.您可以使用以下命令创建它并将生成的扇区放入其中:
nasm -f bin main.asm -o main.bin

创建一个 516096 字节的图像:
dd if=/dev/zero of=disk.img count=1008 bs=512

将引导扇区置于 disk.img 的开头不截断文件:
dd if=main.bin of=disk.img conv=notrunc

我在此 Stackoverflow answer 中有关于使用 DD 创建磁盘镜像的其他信息.

一般代码观察

尽管磁盘镜像是 BOCHS 问题的一部分,但您确实有一些编码问题。当控制权从 BIOS 转移到引导加载程序时,您不能假设 CS 的值将设置为您的想法。看我的 General Bootloader Tips想要查询更多的信息。如果您希望 DS 和 ES 为零(这是您对 org 0x7c00 所需要的),您应该将代码的开头修改为:
org 0x7c00
bits 16

boot:
cli

xor ax, ax ; Explicitly set DS and ES to 0
mov ds, ax
mov es, ax

为了测试你的代码,我在 bootend 之后添加了这个:
bootend:

; Print MDP to upper left of screen in white on light magenta
mov ax, 0xb800
mov es, ax
mov word [es:0x0000], 0x57<<8 | 'M'
mov word [es:0x0002], 0x57<<8 | 'D'
mov word [es:0x0004], 0x57<<8 | 'P'

; Infinite loop so we don't have the CPU wander memory
cli
endloop:
hlt
jmp endloop

我不确定这一行是不是打字错误,或者您在将程序集文件传递给 NASM 之前在程序集文件上使用了某种类型的预处理器。通常这条线会是 % 的问题前符号 1 :
dw %1 ; Number of sectors to be loaded

NASM 只会直接支持这一点:
dw 1  ; Number of sectors to be loaded

真实硬件/USB/笔记本电脑问题

如果您尝试使用 USB 在真实硬件上启动,那么即使您通过上述更改使其在 BOCHS 中工作,您也可能会遇到另一个问题。如果您的 BIOS 设置为进行 USB FDD 仿真(而不是 USB HDD 或其他东西),您可能需要添加 Boot Parameter Block(BPB)到引导加载程序的开头。你可以像这样创建一个假的:
org 0x7c00
bits 16

boot:
jmp main
TIMES 3-($-$$) DB 0x90 ; Support 2 or 3 byte encoded JMPs before BPB.

; Dos 4.0 EBPB 1.44MB floppy
OEMname: db "mkfs.fat" ; mkfs.fat is what OEMname mkdosfs uses
bytesPerSector: dw 512
sectPerCluster: db 1
reservedSectors: dw 1
numFAT: db 2
numRootDirEntries: dw 224
numSectors: dw 2880
mediaType: db 0xf0
numFATsectors: dw 9
sectorsPerTrack: dw 18
numHeads: dw 2
numHiddenSectors: dd 0
numSectorsHuge: dd 0
driveNum: db 0
reserved: db 0
signature: db 0x29
volumeID: dd 0x2d7e5a1a
volumeLabel: db "NO NAME "
fileSysType: db "FAT12 "

main:
cli

xor ax, ax ; Explicitly set DS and ES to 0
mov ds, ax
mov es, ax
[rest of your code here]

如果您要修改代码以使其布局高于 Unix/Linux file命令可能能够转储它认为构成磁盘镜像中 MBR 的 BPB 数据。运行命令 file disk.img你可能会得到这个输出:

disk.img: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", root entries 224, sectors 2880 (volumes <=32 MB) , sectors/FAT 9, sectors/track 18, serial number 0x2d7e5a1a, unlabeled, FAT (12 bit)



带有 Int 13h 扩展检查的完整示例

以下代码将检查 BIOS 中的 Int 13h 扩展是否可用,并且还将确定 DL 中的驱动器是否支持 Int 13h 扩展。如果出现故障,代码将打印适当的错误。 A print_string函数用于使用 BIOS TTY 输出和 print_hex_word 向控制台显示字符串。提供了以十六进制显示引导驱动器编号的功能。
org 0x7c00
bits 16

section .text
boot:
jmp main
TIMES 3-($-$$) DB 0x90 ; Support 2 or 3 byte encoded JMPs before BPB.

; Dos 4.0 EBPB 1.44MB floppy
OEMname: db "mkfs.fat" ; mkfs.fat is what OEMname mkdosfs uses
bytesPerSector: dw 512
sectPerCluster: db 1
reservedSectors: dw 1
numFAT: db 2
numRootDirEntries: dw 224
numSectors: dw 2880
mediaType: db 0xf0
numFATsectors: dw 9
sectorsPerTrack: dw 18
numHeads: dw 2
numHiddenSectors: dd 0
numSectorsHuge: dd 0
driveNum: db 0
reserved: db 0
signature: db 0x29
volumeID: dd 0x2d7e5a1a
volumeLabel: db "NO NAME "
fileSysType: db "FAT12 "

main:
cli
cld ; String instructions forward movement

xor ax, ax
mov ds, ax
mov es, ax
; Setup 4K stack before this bootloader
mov ss, ax
mov sp, 0x7c00

; Display a banner to know our bootloader is executing
mov si, msg_booting
call print_string

; Check that Int 13h Extensions are available
; http://www.ctyme.com/intr/rb-0706.htm

mov ah, 0x41 ; Int 13h/AH=41h: Check if extensions present
mov bx, 0x55aa
int 0x13
jc ext_drv_none ; CF set - no extensions available for drive
cmp bx, 0xaa55 ; Is BX 0xaa55?
jnz ext_none ; If not, int 13h extensions not supported
; by BIOS at all.

; Int 13h extensions supported by BIOS and drive at this point
; Load next sectors
mov si, DAP
mov ah, 42h
; DL didn't changed
int 13h
; Start
jmp bootend

; Error: BIOS doesn't support Int 13h extensions
ext_none:
mov si, err_no_extensions
call print_string
jmp error_end

; Error: BIOS supports Int 13h extensions but not for drive in DL
ext_drv_none:
mov si, err_no_drv_ext_support
call print_string

; Print the boot drive number in hex
xor dh, dh ; Zero extended drive number to all of DX
push word 0x00 ; Attribute and page number to write to
push dx ; The value to write as hex
call print_hex_word


error_end:
cli
.loop:
hlt
jmp .loop

; Print 16 bit value passed on stack as first parameter
; in hexadecimal. Use page number and foreground color
; passed in second parameter. This routine will work on 8086+
; processors. This code takes advantage of packed BCD to
; determine the ASCII values to print. This code could have
; used compare and branch to do the same or a translation table.

print_hex_word:
push bp
mov bp, sp ; BP=SP, on 8086 can't use sp in memory operand
push dx ; Save all registers we clobber
push cx
push bx
push ax

mov cx, 0x0404 ; CH = number of nibbles to process = 4 (4*4=16 bits)
; CL = Number of bits to rotate each iteration = 4 (a nibble)
mov dx, [bp+4] ; DX = word parameter on stack at [bp+4] to print
mov bx, [bp+6] ; BX = page / foreground attr is at [bp+6]

.loop:
rol dx, cl ; Roll 4 bits left. Lower nibble is value to print
mov ax, 0x0e0f ; AH=0E (BIOS tty print),AL=mask to get lower nibble
and al, dl ; AL=copy of lower nibble
add al, 0x90 ; Work as if we are packed BCD
daa ; Decimal adjust after add.
; If nibble in AL was between 0 and 9, then CF=0 and
; AL=0x90 to 0x99
; If nibble in AL was between A and F, then CF=1 and
; AL=0x00 to 0x05
adc al, 0x40 ; AL=0xD0 to 0xD9
; or AL=0x41 to 0x46
daa ; AL=0x30 to 0x39 (ASCII '0' to '9')
; or AL=0x41 to 0x46 (ASCII 'A' to 'F')
int 0x10 ; Print ASCII character in AL
dec ch
jnz .loop ; Go back if more nibbles to process

pop ax ; Restore registers
pop bx
pop cx
pop dx
pop bp
ret

; Print string pointed to by DS:SI using
; BIOS TTY output via int 10h/AH=0eh

print_string:
push ax
push si
mov ah, 0Eh ; int 10h 'print char' function

.repeat:
lodsb ; Get character from string
test al, al
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
pop si
pop ax
ret

; Disk address packet
DAP:
db 10h, 0
dw 1 ; Number of sectors to be loaded
dd bootend
dq 1

msg_booting: db "Booting... ", 0x00
err_no_extensions: db "Int 13h extensions not supported by BIOS", 0x00
err_no_drv_ext_support: db "Int 13h Extensions not supported on drive 0x", 0x00

; Fill the rest of bootsector with zeroes and end it
times 510 - ($ - boot) db 0
dw 0xAA55
bootend:

mov ax, 0xb800
mov es, ax
mov word [es:0x0000], 0x57<<8 | 'M'
mov word [es:0x0002], 0x57<<8 | 'D'
mov word [es:0x0004], 0x57<<8 | 'P'
cli
hlt

使用这些信息使其成为上面的硬盘镜像,当我在 BOCHS 中运行它时,我得到以下输出:

enter image description here

如果我在 BOCHS 中启动与软盘(磁盘 A:)相同的镜像,错误消息现在告诉我 Int 13h 扩展不适用于驱动器 0x0000:

enter image description here

如果您发现需要读取不支持 Int 13h 扩展的设备,您将不得不回退到 reading 的标准 Int 13h 磁盘子函数。 (AH=02)/ writing (AH=03)。

关于x86 - int 13h 42h 在 Bochs 中不加载任何东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43786251/

26 4 0
文章推荐: java - 调用notifyAll有什么好的解决方案吗?
文章推荐: .net - WebMethod 响应格式
文章推荐: java - 无法从 Vector 转换为 Integer