INT 0x13 / AH = 0x02 работает с образом дискеты, но не при записи на флешку

Я пытаюсь создать простую систему команд в сборке x86. Система команд - это второй этап, который загружается в 0x1000: 0000. Чтобы увидеть мой загрузчик, щелкните в этом вопросе о stackoverflow.

Вот система команд второго этапа:



[BITS 16]
[ORG 0x0000]      

mov ax, cs
mov ds, ax   
xor cx, cx  
mov bx, welcome_msg
call str_prt
call new_line
mov bx, creator_msg
call str_prt
call new_line
mov bx, boot_msg
call str_prt
call new_line
mov bx, [buffer]

call new_line

mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
mov al, '>'
int 0x10

loop:
in al, 64h  
test al, 1    
je loop
xor ah, ah
int 0x16
call key_scan
jmp loop

key_scan:
cmp al, 0x08
je back_space
cmp al, 0x0d
je enter
cmp cx, 0x0015 
je end
mov ah, 0x0e
int 0x10
mov bx, buffer
add bx, cx
mov [bx], al
inc cx
jmp end
back_space:
cmp cx, 0x00
je end
dec cx
mov ah, 0x0e
mov al, 0x08
int 0x10
mov al, 0x20
int 0x10
mov al, 0x08
int 0x10
jmp end
enter:
xor cx, cx
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
call pro_com
call clear_buffer
mov ah, 0x0e
mov al, '>'
int 0x10
end:
ret

str_prt:
pusha
str:
mov ah, 0x0e
mov al, [bx]
cmp al, '$'
je str_end
int 0x10
add bx, 1
jmp str
str_end:
popa
ret

new_line:
push ax
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
pop ax
ret

clear_buffer:
push ax
push bx
push cx
mov bx, buffer
xor cx, cx
xor ax, ax
start:
cmp cx, 0x41
je end_buff
mov [bx], ax
inc bx
inc cx
jmp start
end_buff:
pop cx
pop bx
pop ax
ret

pro_com:
push bx
push ax
mov bx, buffer
mov al, [bx]
cmp al, 'h'
jne help_end
inc bx
mov al, [bx]
cmp al, 'e'
jne help_end
inc bx
mov al, [bx]
cmp al, 'l'
jne help_end
inc bx
mov al, [bx]
cmp al, 'p'
jne help_end
call com_help
jmp pro_end
help_end:
mov bx, buffer
mov al, [bx]
cmp al, 'd'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'i'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'r'
jne dir_end
call com_dir
jmp pro_end
dir_end:
mov bx, not_found
call str_prt
call new_line
pro_end:
pop ax
pop bx
ret

com_help:
push bx
call new_line
mov bx, help1_msg
call str_prt
call new_line
call new_line
pop bx
ret

com_dir:
push ax
push bx
push cx
push dx
mov bx, drive_num
mov dl, [bx]
mov cl, 0x09
mov al, 0x01
mov ch, 0x00
mov cl, 0x09
mov dh, 0x00
com_dir_loop:
call read_dir
cmp cl, 0x12
je false1
inc cx
jmp com_dir_loop
false1:
pop dx
pop cx
pop bx
pop ax 
ret

read_dir:
push ax
push bx
mov bx, 0x1000
mov es, bx
mov bx, 0xe00
call read_disc
clc
mov bx, 0x0e00
mov al, [bx]
cmp al, 'F'
jne read_dir_end
;print file name
mov bx, 0x0e01
call str_prt
call new_line
;----
read_dir_end:
pop bx
pop ax 
mov bx, 0x1000
mov es, bx
ret

read_disc:
mov ah, 0x02   
int 0x13   
ret

buffer times 20 db 0

drive_num:
db 0


welcome_msg:
db 'Welcome to matriXos$'
creator_msg:
db 'Created by Vishnu Shankar.B$'
boot_msg:
db 'Booting command line interface...$'
not_found:
db 'Command cannot be resolved!$'
help1_msg:
db 'Help not avilable!$'


jmp $
times 3584 - ($ - $$) db 0




Команда «dir» (com_dir) должна читать и печатать строку, начинающуюся с буквы «F», которая помещается в начало, если каждый сектор 9 - 18 (дорожка 0) (CHS). Я разместил строки с помощью шестнадцатеричного редактора.
Я преобразовал код в файл изображения. Он отлично работает в эмуляторе Bochs, но когда я записываю файл образа на флешку и загружаю его на свой компьютер, он печатает мусор.
Может ли кто-нибудь сказать мне, что не так?
Заранее спасибо.


person RainingComputers    schedule 10.12.2015    source источник
comment
Убедитесь, что вы загружаетесь с использованием эмуляции гибкого диска, а не жесткого диска (что является нормальным случаем). Кроме того, ваш код длиннее одного сектора, возможно, вы не загружаете его полностью. Это должно повлиять только на help1_msg, и непонятно, какой у вас код загрузчика (тот, что из принятого ответа?)   -  person Jester    schedule 10.12.2015
comment
@Jester - Похоже, он знает, что код состоит из 7 секторов, если вы посмотрите на оператор times.   -  person owacoder    schedule 10.12.2015
comment
Да, на самом деле код в его другом вопросе имеет эту строку: mov al,0x11 ;Reading one sector, которая смутила меня на секунду, поскольку он загружает 17 секторов, а не один, как говорится в комментарии ...   -  person Jester    schedule 10.12.2015
comment
@ Jester Я изменил свой загрузчик на загрузку 7 секторов. Сектор 8-17 (LBA) загружается через шестнадцатеричный редактор, а не ассемблер.   -  person RainingComputers    schedule 10.12.2015
comment
Вы уверены, что номер накопителя для флешки правильный?   -  person MikeCAT    schedule 10.12.2015
comment
@MikeCAT Нет, я проверю это.   -  person RainingComputers    schedule 10.12.2015
comment
@MikeCAT Мой загрузчик тоже на флешке. Он загружает все с диска с номером 0x00. Это работает правильно.   -  person RainingComputers    schedule 10.12.2015
comment
@MikeCAT Вы правы!   -  person RainingComputers    schedule 10.12.2015


Ответы (1)


В моем предыдущем ответе я случайно удалил строку в вашем загрузчике, которая устанавливает DL на ноль . Ваш загрузчик сделал это:

mov dl,0x0  ;Drive = 0 (Floppy)

Это нужно удалить. Я объяснил причину этого в своем предыдущем ответе с таким комментарием:

Это жестко кодирует загрузочный привод на дискету A :. Если вы загружаетесь с USB, жесткого диска или дискеты B: ваш код не будет работать, потому что в этих случаях номер диска, скорее всего, не будет равен нулю. BIOS передает фактический загрузочный диск, который использовался для загрузки загрузчика. Это значение находится в регистре DL. Это значение, которое вы должны использовать для функций диска BIOS. Поскольку DL уже содержит загрузочный диск, мы просто используем его как есть.

Повторно используйте значение в DL, которое передается вашему загрузчику для чтения и записи диска, но также передайте это значение на второй этап! Поскольку ваш загрузчик на самом деле не уничтожает содержимое DL, вам просто нужно переместить DL в переменную drive_num. Это можно сделать сразу после настройки реестра DS на втором этапе следующим образом:

[BITS 16]
[ORG 0x0000]

mov ax, cs
mov ds, ax
mov [drive_num], dl    ; drive_num = the boot drive the BIOS booted from

Если вы когда-либо изменяли свой загрузчик так, чтобы он уничтожал содержимое регистров DX или DL, вам следует подумать о том, чтобы поместить его в стек после запуска загрузчика, а затем извлечь его. выключить (восстановить) непосредственно перед прыжком на второй этап.

В загрузчике, который я представил вам в предыдущем ответе, я начал так:

xor ax, ax
mov ds, ax        ; DS=0

cli               ; Turn off interrupts for SS:SP update
                  ; to avoid a problem with buggy 8088 CPUs
mov ss, ax        ; SS = 0x0000
mov sp, 0x7c00    ; SP = 0x7c00
                  ; We'll set the stack starting just below
                  ; where the bootloader is at 0x0:0x7c00. The
                  ; stack can be placed anywhere in usable and
                  ; unused RAM.
sti               ; Turn interrupts back on

После настройки стека мы можем сохранить регистр DX, выполнив следующие действия:

xor ax, ax
mov ds, ax        ; DS=0

cli               ; Turn off interrupts for SS:SP update
                  ; to avoid a problem with buggy 8088 CPUs
mov ss, ax        ; SS = 0x0000
mov sp, 0x7c00    ; SP = 0x7c00
                  ; We'll set the stack starting just below
                  ; where the bootloader is at 0x0:0x7c00. The
                  ; stack can be placed anywhere in usable and
                  ; unused RAM.
sti               ; Turn interrupts back on
push dx           ; Save DX register (which includes DL) on stack

Теперь, когда он сохранен, мы можем восстановить его значение непосредственно перед тем, как перейти ко второму этапу. Этот код:

jmp 0x1000:0000   ; Jump to 0x1000, start of second stage

Теперь сделал бы это:

pop dx            ; Restore DX register (which includes DL)
jmp 0x1000:0000   ; Jump to 0x1000, start of second stage

Это эффективно передает DL (загрузочный диск) на наш второй этап даже в том случае, если мы можем уничтожить его содержимое во время выполнения нашего загрузчика. Затем наш второй этап имеет возможность повторно использовать это значение для чтения и записи собственного диска BIOS.

person Michael Petch    schedule 10.12.2015