Сбой инициализации накопителя INT 0x13 с ошибкой тайм-аута - PullRequest
1 голос
/ 30 апреля 2020

Я пытаюсь разработать загрузчик, который просто сканирует каталог root своего загрузочного носителя (дискета с FAT16) на наличие файла и переходит к нему. Я, наконец, столкнулся с проблемой, которую нигде не обнаружил в сети, и чувствую, что сделал что-то не так: при запуске моего кода, когда я читаю каталог root диска, используя INT 0x13, устанавливается флаг переноса и после того, как я заставил его распечатать код ошибки, который приходит в AH, я получил 0x80, который, кажется, соответствует тайм-ауту диска. Я уже пробовал жестко кодировать DL до 0x00 (дискета # 1 - то же, что и раньше), 0x01 (дискета # 2 - AH = 0x01 недопустимая функция) и 0x80 (жесткий диск # 1 - на самом деле были данные, но, как и ожидалось, не тот, что из образ дискеты). Я также пытался жестко запрограммировать вычисление параметров и пытался читать только один сектор. Ниже приведен код, в котором, по-видимому, происходит ошибка:

    BITS 16

    jmp short bootload
    nop

    ; Drive parameters

bootload:
    ; Segment registers
    mov ax, 0x07C0+544
    cli
        mov ss, ax
        mov sp, 4096
    sti

    mov ax, 0x07C0
    mov ds, ax
    mov es, ax

    ; Boot device
    mov [bootdev], dl

    ; Calculations (I just hardcoded them in this example to make it easier to understand)
    mov byte [rootdirsize], 14
    mov byte [rootdirchssec], 1
    mov word [rootdirchstrack], 1

    ; Read sectors
    mov ah, 0x02                        ; Read sectors
    mov al, byte [rootdirsize]          ; The amount of sectors needed by the root dir entries
                                        ; (RootDirEntries / 16)
    mov dl, byte [bootdev]
    mov dh, 0                           ; Heads are ignored... yet
    mov cl, byte [rootdirchssec]        ; Sector number of the root dir in CHS
    and cx, 0b0000_0000_0011_1111       ; Sector only uses bits 0-5 of CX
    mov bx, word [rootdirchstrack]      ; Track number of the root dir in CHS
    shl bx, 6                           ; Track uses bits 6-15 of CX
    or cx, bx                           ; Transfer to CX
    mov bx, 0x0100                      ; Segment where it is loaded
    mov es, bx
    mov bx, 0                           ; Offset = 0
    int 0x13

    jc disk_error                       ; CF = error

    jmp $                               ; the rest of the bootloader

disk_error:
    mov al, ah                          ; AH is the error code
    mov ah, 0x0E                        ; print it
    int 0x10                            ; returns 'Ç' = 0x80 = timeout

    jmp $

data:
    bootdev         db 0
    rootdirsec      dw 0
    rootdirchssec   db 0
    rootdirchstrack dw 0
    rootdirsize     db 0

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

Реальный код, конечно, намного длиннее, я пытался писать только те части, которые важны для проблемы. Другие сведения, которые могут помочь:

  • Я использую NASM
  • Я тестирую на VMWare Workstation с виртуальной дискетой
  • Другой код работает нормально (например, , распечатывая материал или взаимодействуя с клавиатурой)
  • Я сделал несколько снимков для проверки виртуальной памяти с помощью шестнадцатеричного редактора, данные диска (кроме загрузочного кода) никогда не загружались в память

1 Ответ

1 голос
/ 01 мая 2020

Вы правы, что Цилиндры (дорожки) могут быть 10-разрядными числами, а номер сектора для чтения равен 6 битам. Оба упакованы в 16-битный регистр ( CX ) для вызова чтения диска int 0x13 B IOS. 10-битные номера цилиндров относятся только к носителям типа жесткого диска (или к чему-либо, эмулируемому как жесткий диск). С дискетами Носители ограничены 8-битными значениями (0-255), а номер сектора по-прежнему ограничен значениями от 1 до 63 (6 бит).

Загружается 16-битное слово, содержащее цилиндры в BX для выполнения расчетов. Вы сдвигаете BX влево на 6 бит. Это помещает младшие 2 бита числа цилиндров в верхние 2 бита BL , а старшие 8 бит в регистр BH . Это не то, как кодируется номер цилиндра. Документация для INT 13h / AH = 2 гласит:

CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5)
high two bits of cylinder (bits 6-7, hard disk only)

Это говорит о том, что это старшие 2 бита номера цилиндра, которые должны храниться в старшие 2 бита CL , а номер сектора - младшие 6 битов CL . CH содержит 8 младших бит номера цилиндра.

Чтобы исправить это, вы можете изменить следующие строки:

mov bx, word [rootdirchstrack]  ; Track number of the root dir in CHS
shl bx, 6                       ; Track uses bits 6-15 of CX
or cx, bx                       ; Transfer to CX

на что-то похожее на:

mov bx, word [rootdirchstrack]  ; Track*Cylinder) number of the root dir in CHS    
xchg bl, bh                     ; Place lower 8 bits of Cylinder in BH
                                ; Upper 2 bits of Cylinder are now the lower 2 bits of BL
ror bl, 2                       ; Rotate the lower 2 bits into the upper 2 bits of BL
or cx, bx                       ; Transfer to CX already containing sec # in lower 6 bits
...