int 13h 42h 在 Bochs 中不加载任何东西 [英] int 13h 42h doesn't load anything in Bochs

查看:16
本文介绍了int 13h 42h 在 Bochs 中不加载任何东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将引导加载程序从 CHS 更改为 LBA,因此我将 int 13h 02h 替换为 int 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位 16引导:命令行;重叠 CS 和 DSmov ax, csmov ds, 斧头移动,斧头;在此引导加载程序之前设置 4K 堆栈移动斧头,0x07c0mov ss, 斧头mov sp, 4096;加载下一个扇区mov si, DAP动啊,42h;DL没变13 小时;开始jmp 引导端;磁盘地址包行动党:分贝 10 小时,0dw %1 ;要加载的扇区数dd 引导端dq 1;用零填充引导扇区的其余部分并结束它时间 510 -($ - 引导)db 0dw 0xAA55引导端:

bochsrc:

兆:32romimage:文件=/usr/share/bochs/BIOS-bochs-latest,地址=0xfffe0000vgaromimage: 文件=/usr/share/bochs/VGABIOS-lgpl-latest软盘:1_44=main.bin,状态=插入引导:一个恐慌:行动=问日志:bochsout.txt鼠标:启用=0键盘:type=mf,serial_delay=200,paste_delay=100000display_library: x, options="gui_debug"

解决方案

LBA 磁盘访问可用性

并非所有 BIOS 都支持扩展磁盘读写功能(尽管在现代硬件上它们几乎都支持).并非所有 BIOS 都支持通过

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

如果您发现需要读取不支持 Int 13h 扩展的设备,您将不得不回退到 阅读 (AH=02)/写作 (AH=03).

I changed my bootloader from CHS to LBA, so I replaced int 13h 02h with int 13h 42h. It works correctly in QEMU, however, I have troubles running it with Bochs and my laptop.

I wrote bootloader to USB flash drive with dd if=main.bin of=/dev/sdb bs=512. Laptop loads Intel UNDI and gives me the following error: No bootable device - insert boot disk and press any key.

So I tried to debug it with Bochs and noticed that Bochs recognizes this binary file as bootable. However, nothing had been loaded after int 13h executed.

Then I tried to load my old PC from this flash drive, and it works! It loads program and executes it correctly. QEMU gives me the same result.

Here is the bootloader code:

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 Disk Access Availability

Not all BIOSes support the extended disk read and write functions (although on modern hardware they almost all likely will). Not all BIOSes support extended disk reads of floppies via Int 13h/AH=42h. This is true of BOCHS as well. You can test whether extended disk functions are available on a drive via Int 13/AH=41h/BX=55AAh. This does an extended disk installation check.

If you want to test your code on BOCHS using extended disk reads and LBA you will have to create a hard disk image and modify BOCHS to boot from it instead of floppy. The minimum size hard disk image size that BOCHS supports is one with CHS = 1/16/63 which is 512*16*63 = 516096 bytes or 1008 sectors of 512 bytes each.

You can modify your bochsrc.txt to be:

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"

I use a disk image called disk.img. You can create it and place the sectors you generate into it with commands like:

nasm -f bin main.asm -o main.bin

Create an image of 516096 bytes:

dd if=/dev/zero of=disk.img count=1008 bs=512

Place the boot sectors into the beginning of disk.img without truncating the file:

dd if=main.bin of=disk.img conv=notrunc

I have additional information on using DD to create disk images in this Stackoverflow answer.


General Code Observations

Although the disk image is part of the issue with BOCHS you do have some coding issues. You can't assume the value of CS will be set to what you think when control is transferred from the BIOS to your bootloader. See my General Bootloader Tips for more information. If you want DS and ES to be zero (which is what you'd need with org 0x7c00), you should modify the start of your code to be something like:

org 0x7c00
bits 16

boot:
    cli

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

To test out your code I added this after 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


I'm not sure this line is a typo or you are using some type of pre-processor on your assembly files before passing them to NASM. Normally this line would be a problem with the % symbol before 1:

dw %1 ; Number of sectors to be loaded

NASM would only support this directly:

dw 1  ; Number of sectors to be loaded


Real Hardware / USB / Laptop Issues

If you are attempting to use USB to boot on real hardware then you may encounter another issue even if you get it working in BOCHS with the changes above. If your BIOS is set to do USB FDD emulation (and not USB HDD or something else) you may need to add a Boot Parameter Block(BPB) to the beginning of your bootloader. You can create a fake one like this:

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]

If you were to modify your code to have the layout above the Unix/Linux file command may be able to dump out the BPB data that it thinks makes up your MBR in the disk image. Run the command file disk.img and you may get this output:

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)


Complete Example with Int 13h Extension Checks

The following code will check that Int 13h extensions are available in the BIOS and will also determine if the drive in DL supports Int 13h extensions. If there is a failure the code will print an appropriate error. A print_string function is used to display strings to the console using BIOS TTY output and a print_hex_word function is provided to display the boot drive number in hexadecimal.

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

Using the information to make this a hard disk image above, when I run it in BOCHS I get this output:

If I boot this same image as a floppy disk (disk A:) in BOCHS the error message now tells me that Int 13h extensions aren't available for drive 0x0000:

If you find that you need to read a device that doesn't support Int 13h extensions you will have to fall back to the standard Int 13h disk subfunctions for reading (AH=02)/writing (AH=03).

这篇关于int 13h 42h 在 Bochs 中不加载任何东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆