Ошибка при создании загрузочной дискеты, содержащей загрузчик и ядро

Я пытаюсь создать загрузочную дискету для файлов boot.bin и kernel.bin. Мой код boot.asm:

bits 16

section .text
start:         
JMP MAIN

WAIT_FOR_KEY:
MOV AH, 00H
INT 16H
RET

CLEAR:
MOV AH, 0H                       ;CHANGING THE VIDEO MODE TO CLEAR THE SCREEN 
MOV AL, 03H                      ;VIDEO MODE COD
INT 10H
RET

LOG_TO_HTS:
PUSH BX
PUSH AX
MOV BX, AX
MOV DX, 0
DIV WORD[ALL_SECTORS]
ADD DL, 01H
MOV CL, DL
MOV AX, BX
MOV DX, 0
DIV WORD [ALL_SECTORS]
MOV DX, 0 
DIV WORD[FACES]
MOV DH, DL
MOV CH, AL
POP AX
POP BX
MOV DL, BYTE [BOOT_DEVICE]
RET

ECHO:                   ;-=-=-=PRINTING FUNCTION =-=-=-;
LODSB                   ;MOV ONE CHAR FROM SI TO AL AND DELETE IT FROM SI
CMP AL, 0               ;CHECK IF THE VALUE IN AL=0, IF ITS ZERO THEN WE
JE DONE                 ;WE ARE DONE PRINTING, AND JUMP BACK TO THE MAIN FUNCTION
CMP AL, 59
JE NEWLINE
MOV AH, 0EH             ;THE FUNCTION CODE FOR PRINTING (TELETYPE PRINTING)
INT 10H                 ;BIOS CALL
JMP ECHO                ;IF WE ARRIVED TO THIS LINE THATS MEAN WE ARE NOT DONE WITH
                        ;PRINTING THE WHOLE STREING SO JUMP BACK AND COMPLETE THE PROCESS

DONE:                   ;LABEL CONTAINS ONE INSTRUCTION TO JUMP BACK TO THE LINE 
RET                     ;WHERE WE CALLED THE ECHO FUNCTION

NEWLINE:
PUSHA
MOV AH, 0EH
MOV AL, 13
INT 10H
MOV AL, 10
INT 10H 
POPA
RET

RESET_DRIVE:                                ;RESET FLOPPY DRIVE FUNCTION
MOV AX, 0                           ;THE FUNCTION CODE TO RESET DRIVE
MOV DL, BYTE [BOOT_DEVICE]                          ;DRIVE ID TO RESET
INT 13H
RET


MAIN:                            ;THE MAIN FUNCTION LABEL


;TO BEGIN LOADING EXTERNAL FILE LIKE KERNEL SOME THINGS MUST BE DONE LIKE :
;1- SETTING UP THE STACK
;2- SETTING UP THE SEGMENTS
;3- SPECIFY THE BOOT DRIVE

;SETTING UP THE STACK
CLI                             ;CLEAR INTERRUPTS TO SET THE SEGMENT

XOR AX, AX                       ;SET THE BOTTOM OF THE STACK
MOV SS, AX
MOV SP, 0XFFFF                  ;SET THE TOP OF THE STACK
STI                             ;RESTORE THE INTERRUPTS

;SETTING UP THE SEGMENTS
MOV AX, 07C0H
MOV DS, AX
MOV ES, AX
;AFTER SETTING UP SEGMENTS AND STACK, YOU ARE FREE TO CODE WHAT EVER YOU WANT
;THE CPU WILL RECOGNISE YOUR CODE AS A BOOTLOADER

CALL CLEAR
;MOV SI, WELCOME_MSG
;CALL ECHO


MOV [BOOT_DEVICE], DL          ;SAVE THE DRIVE ID TO USE IT LATER


;WE WILL USE IN 13H TO LOAD ROOT DIR. THAT WE NEED TO LOAD THE FIRST SECTOR OF THE KERNEL
;THEN WE WILL LOAD FAT TO LOAD THE WHOLE KERNEL SINCE THE FILE LOAD PROCESS CONSISTS OF 3 STEPS
;1- LOAD THE FISRT SECTOR OF THE FILE
;2- LOAD THE WHOLE FILE AND COPY IT INTO RAM
;3- EXCUTE THE FILE
;THE ROOT DIR. AND FAT ARE LOCATED IN SOMEWHERE ON THE FLOPPY DRIVE AS FOLLOWS

;1- SETTING UP AND LOADING THE ROOT DIR.
MOV AH, 02H                     ;THE FUNCTION CODE FOR LOADING ROOT DIR.
MOV AL, 14                      ;THE SIZE OF THE ROOT DIR. THE ROOT DIR. = 14 AND WE WANT TO LOAD IT ALL SO AL=14
MOV BX, TEMP                            ;THE TEMP STORAGE FOR THE DATA WILL BE READED OR LOADED
MOV CH, 0                       ;TRACK WE WANT TO LOAD, ITS TRACK 0 BEACUSE THE ROOT DIR. LOCATED THERE (CYLINDER)
MOV CL, 2                       ;SECTOR WE WANT TO LOAD, ITS SECTOR 2 BEACUSE THE ROOT DIR. LOCATED THERE
MOV DH, 1                       ;HEAD WE WANT TO LOAD, ITS HEAD 1 BEACUSE THE ROOT DIR. LOCATED THERE
PUSHA                           ;TO BE ABLE TO RETRY TO LOAD ROOT DIR. IF INT 13H FAILED
LOAD_RD:
INT 13H
JNC LOAD_RD_DONE                        ;IF WE ARRIVE HERE, THATS MEAN THAT THE ROOT DIR. LOADED SUCCESSFULLY
CALL RESET_DRIVE                        ;RESET FLOPPY FUNCTION CALL
JMP LOAD_RD                     ;RETRY IF INT 13H FAILED


LOAD_RD_DONE:
POPA
;NOW WE WILL SEARCH IN THE ROOT DIR. TABLE IF IT CONTAINS THE DESIRED FILE NAME WHICH IS KERNEL.BIN
;WE WILL USE CMPSB INSTRUCTION THAT COMPARES THE VALUE OF DS:SI AND ES:DI
;ES AND DS ARE ALREADY SET
;THE SEARCH WILL BE LIMITED TO SEARCH AMONG 11 BYTES BECAUSE THE FILE NAME IS 11 BYTES

MOV DI, TEMP                            ;THE RESULT WE GOT (THE ENTRY)
MOV CX, 224                     ;THE MAX. POSSIBLE FILE NUMBER THAT WE COULD HAVE IS 224 SO WE LIMIT THE SEARCH TO IT (THE VALUE THAT WILL BE DECREASED WHILE LOOPING)

FIND_KERNEL:
PUSH CX                         ;PUSH CX AND DI BECAUSE THEY HELD IMPORTANT DATA THAT WE DONT WANT TO LOSE
POP DX                      
MOV SI, FILE_NAME                       ;THE VALUE THAT WE WILL COMPARE THE RESULT OF ROOT DIR. TO FIND
MOV CX, 11                      ;TO REPEATE THE SEARCH PROCESS 11 TIMES(THE FILE NAME LENGTH)
REP CMPSB                       ;COPMARES SI WITH DI

JE FOUND_KERNEL                         ;IF WO GO TO THE NEXT LINE, THAT MEANS THAT THE KERNEL IS NOT FOUNDED YET
;AND SINCE DI IS POINTS TO THE FIRST ENTRY, WE NEED TO MOVE TO THE NEXT ONE BY ADDING 32

ADD AX, 32
MOV DI, TEMP
ADD DI, AX
PUSH DX
POP CX

LOOP FIND_KERNEL
;IF WE ARE HERE, THEN THE KERNEL IS NOT EXISTS
;MOV SI, FAILED_TO_LOAD_KERNEL
;CALL ECHO
CLI
INT 18H                         ;CRASH AND HALT THE PROCESSOR


FOUND_KERNEL:                                           ;IF WE FOUND THE KERNEL WE WILL BE HERE
;NOW WE HAVE THE ENTRY POINT FOR THE KERNEL SAVED IN DL REGISTER
;WE GOT THE KERNEL FROM THE FIRST 11 BYTES SO WE NEED TO ADD 15 TO GET TO THE 26 BYTES
;THE FIRST SECTOR IS LOCATED AT 26 AND 27 SO WE MUST ADD 15 TO LOAD THE KERNEL IN THE FIRST SECTOR
MOV AX, WORD [DI+15]                            ;WORD ADDED TO COPY BOTH 26 AND 27 BYTES TO AX, THE WORD IS 2 BYTES
MOV [ENTERY_POINT], AX



;2- SETTING UP AND LOADING THE FAT
MOV AX, 1
MOV BX, TEMP                            ;THE TEMP STORAGE FOR THE DATA WILL BE READED OR LOADED
CALL LOG_TO_HTS
MOV AH, 2                       ;THE FUNCTION CODE FOR LOADING ROOT DIR.
MOV AL, 9                       ;THE SIZE OF THE ROOT DIR. THE ROOT DIR. = 14 AND WE WANT TO LOAD IT ALL SO AL=14
PUSHA                           ;TO BE ABLE TO RETRY TO LOAD ROOT DIR. IF INT 13H FAILED
LOAD_FAT:
INT 13H
JNC LOAD_FAT_DONE                       ;IF WE ARRIVE HERE, THATS MEAN THAT THE FAT LOADED SUCCESSFULLY
CALL RESET_DRIVE                        ;RESET FLOPPY FUNCTION CALL
JMP LOAD_FAT                            ;RETRY IF INT 13H FAILED


LOAD_FAT_DONE:                          ;IF LOADING FAT DONE SUCCESSFULLY, WE WILL BE HERE
MOV AH, 2
MOV AL, 1 
PUSH AX

LOAD_SECTOR:                            ;ROOT DIR. GIVES US A DATA SECTOR AND WE WANT A LOGICAL SECTOR, WE WILL DO IT HERE
MOV AX, WORD [ENTERY_POINT]
ADD AX, 31                      ;31 ADDED TO DONE THE CONVERTION

CALL LOG_TO_HTS                         ;COVERTS THE LOGICAL SECTORS INTO HEAD TRACK SECTORS
MOV AX, 2000H
MOV ES, AX
MOV BX, WORD[OFFSET_]
POP AX
PUSH AX

INT 13H
JNC GET_NEXT
CALL RESET_DRIVE
JMP LOAD_SECTOR

GET_NEXT:
MOV AX, [ENTERY_POINT]
MOV DX, 0
MOV BX, 6
MUL BX
MOV BX, 4
DIV BX
MOV SI, TEMP
ADD SI, AX
MOV AX, WORD[SI]

OR DX, DX
JZ EVEN

ODD:
SHR AX, 4
JMP SHORT COMP_SECTOR

EVEN:
AND AX, 0FFFH

COMP_SECTOR:
MOV WORD [ENTERY_POINT], AX
CMP AX, 0FF8H
JAE END
ADD WORD[OFFSET_], 512
JMP LOAD_SECTOR

END:
;MOV SI, KERNEL_LOADED_MSG
CALL ECHO

CALL WAIT_FOR_KEY

POP AX
MOV DL, BYTE[BOOT_DEVICE]
JMP 2000H:0000H

OFFSET_                 DW      0
ALL_SECTORS             DW      18
FACES                   DW      2
ENTERY_POINT                    DW      0
;FAILED_TO_LOAD_KERNEL                  DB      "Error, Cannot Load The Kernel. Booting Process Aborted;",0
BOOT_DEVICE                             DB              0
FILE_NAME               DB      "KERNEL  BIN"
;WELCOME_MSG                             DB              "Litesoft bootloader  Copyright (C) 2012-2016 By Mohamed El Sayed;",0
;KERNEL_LOADED_MSG                       DB              "Kernel Loaded, Press Any Key To Continue...",0
TIMES   510 - ($-$$)    DB      0               ;LOOK FOR EVERY SINGLE EMPTY BIT AND FILL IT WITH ZERO
                                                        ;TILL THE BOOTLOADER SIZE BE 512 BYTE
DW  0xAA55                                          ;THE BOOT SIGNETUARE, ALWAYS THE SAME

TEMP:                           ;HERE IN BYTE 513 WE HAVE SOME MEMORY THAT WILL NOT BE EXECUTED
;AND WE CAN USE IT AS A TEMP MEMORY

Метод, который я планировал использовать, заключается в создании образа дискеты с помощью dd и записи моего загрузчика в первый сектор, затем его монтирования и копирования в него моего ядра.

Команды, которые я использовал

1- mkdosfs -C floppy.flp 1440 , Эта команда создает образ дискеты

2- dd status=noxfer conv=notrunc if=boot.bin of=floppy.flp ,Эта команда записывает загрузчик в первый сектор

Эти команды работают очень хорошо, и образ дискеты с моим загрузчиком в первом секторе успешно создан.

Проблема возникает, когда я пытаюсь смонтировать образ дискеты, чтобы скопировать на него ядро, используя следующие команды.

rm -rf tmp-loop

mkdir tmp-loop && mount -o loop -t vfat floppy.flp tmp-loop && cp kernel.bin tmp-loop/

Каждый раз, когда я пытаюсь смонтировать образ дискеты, я получаю эту ошибку.

mount: wrong fs type, bad option, bad superblock on /dev/loop0,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.

Каково решение этой ошибки? Я использую Убунту 16.04.


person Moe    schedule 30.08.2016    source источник
comment
Это связано с тем, что когда mkdosfs создавала образ диска, она записывала важные данные в блок параметров BIOS в MBR, которые размещают параметры диска и некоторую информацию DOS, необходимую для работы mount. Когда вы записали свой новый загрузчик, вы перезаписали предыдущий BPB.   -  person Michael Petch    schedule 30.08.2016
comment
@MichaelPetch Тогда что сделать, чтобы это заработало?   -  person Moe    schedule 30.08.2016
comment
Вам нужно будет прочитать BPB из оригинальной MBR, созданной моим mkdosfs (сектор 1/головка 0/цилиндр 0), извлечь ее и записать в свой собственный загрузчик. Я не верю, что есть инструмент Linux, который сделает это за вас. Вы можете написать программу, чтобы сделать это.   -  person Michael Petch    schedule 30.08.2016
comment
@MichaelPetch, я даже не знаю, о чем ты говоришь   -  person Moe    schedule 30.08.2016
comment
en.wikipedia.org/wiki/BIOS_parameter_block   -  person Michael Petch    schedule 30.08.2016
comment
Если вы используете NASM, вы можете попробовать это. Возьмите собственный код загрузчика и поместите его после main в этот шаблон а затем соберите/создайте свой образ диска и дайте мне знать, если он работает. Этот шаблон содержит BPB DOS 4.0 для дискеты 1440 КБ (заголовок буквально взят из загрузочного сектора файла, сгенерированного bymkdosfs -C floppy.flp 1440)   -  person Michael Petch    schedule 30.08.2016
comment
Если ваш загрузчик начинается с этих байтов, ваш образ диска должен продолжать отображаться как основная загрузочная запись в формате FAT12 и должен быть монтируемым в Linux.   -  person Michael Petch    schedule 30.08.2016
comment
Поскольку вы не показали нам свой код загрузчика, я не могу комментировать структуру/макет/данные вашего собственного загрузчика.   -  person Michael Petch    schedule 30.08.2016
comment
Ранее я сказал, что mkdosfs создает BPB DOS 4.0, я имел в виду 3.4 BPB   -  person Michael Petch    schedule 31.08.2016
comment
@MichaelPetch Действительно спасибо за помощь и ответ, кстати, это не работает, это весь исходный код загрузчика   -  person Moe    schedule 31.08.2016
comment
Мой ответ должен решить проблему, с которой вы столкнулись при добавлении моей информации в ваш файл. Проблема была с JMP MAIN и дополнительным фрагментом данных после него. Я также разделил байты данных на отдельные переменные, чтобы это имело больше смысла.   -  person Michael Petch    schedule 31.08.2016
comment
Установка для SP значения 0xFFFF (адрес памяти, который не является четным значением) может привести к снижению производительности. Предпочтительно оставить SP четным значением. Используйте значение 0x0000 вместо 0xFFFF. Когда вы выполняете PUSH, SP уменьшается на 2 перед размещением данных в стеке. 0-0x0000-2=-2=0xFFFE.   -  person Michael Petch    schedule 31.08.2016


Ответы (1)


Вам не хватает правильного блока параметров BIOS (BPB) в начале загрузчика. Эта структура содержит информацию, используемую/обновляемую некоторыми BIOS; может использоваться загрузчиком для чтения файловой системы FAT на неразмеченном носителе, таком как дискета; должен присутствовать для программного обеспечения, такого как mount, чтобы определить, какой тип носителя представляет виртуальный образ дискеты. В случае FAT12 на неразделенном носителе (например, дискете) информация о файловой системе представлена ​​в BPB основной загрузочной записи. Распространенным макетом является EBPB DOS 3.4, и он может выглядеть примерно так:

start:
JMP MAIN
TIMES 3-($-$$) DB 0x90   ; Support 2 or 3 byte encoded JMPs before BPB. 

; Dos 3.4 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   "

Основываясь на приведенном выше EBPB DOS 3.4 и вашем коде boot.asm, этот BPB представляет сектор, аналогичный загрузочному сектору дискеты размером 1,44 МБ, созданному с помощью mkdosfs -C floppy.flp 1440:

bits 16

section .text
start:
JMP MAIN
TIMES 3-($-$$) DB 0x90   ; Support 2 or 3 byte encoded JMPs before BPB. 

; Dos 3.4 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   "

WAIT_FOR_KEY:
MOV AH, 00H
INT 16H
RET

CLEAR:
MOV AH, 0H                       ;CHANGING THE VIDEO MODE TO CLEAR THE SCREEN 
MOV AL, 03H                      ;VIDEO MODE COD
INT 10H
RET

LOG_TO_HTS:
PUSH BX
PUSH AX
MOV BX, AX
MOV DX, 0
DIV WORD[ALL_SECTORS]
ADD DL, 01H
MOV CL, DL
MOV AX, BX
MOV DX, 0
DIV WORD [ALL_SECTORS]
MOV DX, 0 
DIV WORD[FACES]
MOV DH, DL
MOV CH, AL
POP AX
POP BX
MOV DL, BYTE [BOOT_DEVICE]
RET

ECHO:                   ;-=-=-=PRINTING FUNCTION =-=-=-;
LODSB                   ;MOV ONE CHAR FROM SI TO AL AND DELETE IT FROM SI
CMP AL, 0               ;CHECK IF THE VALUE IN AL=0, IF ITS ZERO THEN WE
JE DONE                 ;WE ARE DONE PRINTING, AND JUMP BACK TO THE MAIN FUNCTION
CMP AL, 59
JE NEWLINE
MOV AH, 0EH             ;THE FUNCTION CODE FOR PRINTING (TELETYPE PRINTING)
INT 10H                 ;BIOS CALL
JMP ECHO                ;IF WE ARRIVED TO THIS LINE THATS MEAN WE ARE NOT DONE WITH
                        ;PRINTING THE WHOLE STREING SO JUMP BACK AND COMPLETE THE PROCESS

DONE:                   ;LABEL CONTAINS ONE INSTRUCTION TO JUMP BACK TO THE LINE 
RET                     ;WHERE WE CALLED THE ECHO FUNCTION

NEWLINE:
PUSHA
MOV AH, 0EH
MOV AL, 13
INT 10H
MOV AL, 10
INT 10H 
POPA
RET

RESET_DRIVE:                                ;RESET FLOPPY DRIVE FUNCTION
MOV AX, 0                           ;THE FUNCTION CODE TO RESET DRIVE
MOV DL, BYTE [BOOT_DEVICE]                          ;DRIVE ID TO RESET
INT 13H
RET


MAIN:                            ;THE MAIN FUNCTION LABEL


;TO BEGIN LOADING EXTERNAL FILE LIKE KERNEL SOME THINGS MUST BE DONE LIKE :
;1- SETTING UP THE STACK
;2- SETTING UP THE SEGMENTS
;3- SPECIFY THE BOOT DRIVE

;SETTING UP THE STACK
CLI                             ;CLEAR INTERRUPTS TO SET THE SEGMENT

XOR AX, AX                       ;SET THE BOTTOM OF THE STACK
MOV SS, AX
MOV SP, 0XFFFF                  ;SET THE TOP OF THE STACK
STI                             ;RESTORE THE INTERRUPTS

;SETTING UP THE SEGMENTS
MOV AX, 07C0H
MOV DS, AX
MOV ES, AX
;AFTER SETTING UP SEGMENTS AND STACK, YOU ARE FREE TO CODE WHAT EVER YOU WANT
;THE CPU WILL RECOGNISE YOUR CODE AS A BOOTLOADER

CALL CLEAR
;MOV SI, WELCOME_MSG
;CALL ECHO


MOV [BOOT_DEVICE], DL          ;SAVE THE DRIVE ID TO USE IT LATER


;WE WILL USE IN 13H TO LOAD ROOT DIR. THAT WE NEED TO LOAD THE FIRST SECTOR OF THE KERNEL
;THEN WE WILL LOAD FAT TO LOAD THE WHOLE KERNEL SINCE THE FILE LOAD PROCESS CONSISTS OF 3 STEPS
;1- LOAD THE FISRT SECTOR OF THE FILE
;2- LOAD THE WHOLE FILE AND COPY IT INTO RAM
;3- EXCUTE THE FILE
;THE ROOT DIR. AND FAT ARE LOCATED IN SOMEWHERE ON THE FLOPPY DRIVE AS FOLLOWS

;1- SETTING UP AND LOADING THE ROOT DIR.
MOV AH, 02H                     ;THE FUNCTION CODE FOR LOADING ROOT DIR.
MOV AL, 14                      ;THE SIZE OF THE ROOT DIR. THE ROOT DIR. = 14 AND WE WANT TO LOAD IT ALL SO AL=14
MOV BX, TEMP                            ;THE TEMP STORAGE FOR THE DATA WILL BE READED OR LOADED
MOV CH, 0                       ;TRACK WE WANT TO LOAD, ITS TRACK 0 BEACUSE THE ROOT DIR. LOCATED THERE (CYLINDER)
MOV CL, 2                       ;SECTOR WE WANT TO LOAD, ITS SECTOR 2 BEACUSE THE ROOT DIR. LOCATED THERE
MOV DH, 1                       ;HEAD WE WANT TO LOAD, ITS HEAD 1 BEACUSE THE ROOT DIR. LOCATED THERE
PUSHA                           ;TO BE ABLE TO RETRY TO LOAD ROOT DIR. IF INT 13H FAILED
LOAD_RD:
INT 13H
JNC LOAD_RD_DONE                        ;IF WE ARRIVE HERE, THATS MEAN THAT THE ROOT DIR. LOADED SUCCESSFULLY
CALL RESET_DRIVE                        ;RESET FLOPPY FUNCTION CALL
JMP LOAD_RD                     ;RETRY IF INT 13H FAILED


LOAD_RD_DONE:
POPA
;NOW WE WILL SEARCH IN THE ROOT DIR. TABLE IF IT CONTAINS THE DESIRED FILE NAME WHICH IS KERNEL.BIN
;WE WILL USE CMPSB INSTRUCTION THAT COMPARES THE VALUE OF DS:SI AND ES:DI
;ES AND DS ARE ALREADY SET
;THE SEARCH WILL BE LIMITED TO SEARCH AMONG 11 BYTES BECAUSE THE FILE NAME IS 11 BYTES

MOV DI, TEMP                            ;THE RESULT WE GOT (THE ENTRY)
MOV CX, 224                     ;THE MAX. POSSIBLE FILE NUMBER THAT WE COULD HAVE IS 224 SO WE LIMIT THE SEARCH TO IT (THE VALUE THAT WILL BE DECREASED WHILE LOOPING)

FIND_KERNEL:
PUSH CX                         ;PUSH CX AND DI BECAUSE THEY HELD IMPORTANT DATA THAT WE DONT WANT TO LOSE
POP DX                      
MOV SI, FILE_NAME                       ;THE VALUE THAT WE WILL COMPARE THE RESULT OF ROOT DIR. TO FIND
MOV CX, 11                      ;TO REPEATE THE SEARCH PROCESS 11 TIMES(THE FILE NAME LENGTH)
REP CMPSB                       ;COPMARES SI WITH DI

JE FOUND_KERNEL                         ;IF WO GO TO THE NEXT LINE, THAT MEANS THAT THE KERNEL IS NOT FOUNDED YET
;AND SINCE DI IS POINTS TO THE FIRST ENTRY, WE NEED TO MOVE TO THE NEXT ONE BY ADDING 32

ADD AX, 32
MOV DI, TEMP
ADD DI, AX
PUSH DX
POP CX

LOOP FIND_KERNEL
;IF WE ARE HERE, THEN THE KERNEL IS NOT EXISTS
;MOV SI, FAILED_TO_LOAD_KERNEL
;CALL ECHO
CLI
INT 18H                         ;CRASH AND HALT THE PROCESSOR


FOUND_KERNEL:                                           ;IF WE FOUND THE KERNEL WE WILL BE HERE
;NOW WE HAVE THE ENTRY POINT FOR THE KERNEL SAVED IN DL REGISTER
;WE GOT THE KERNEL FROM THE FIRST 11 BYTES SO WE NEED TO ADD 15 TO GET TO THE 26 BYTES
;THE FIRST SECTOR IS LOCATED AT 26 AND 27 SO WE MUST ADD 15 TO LOAD THE KERNEL IN THE FIRST SECTOR
MOV AX, WORD [DI+15]                            ;WORD ADDED TO COPY BOTH 26 AND 27 BYTES TO AX, THE WORD IS 2 BYTES
MOV [ENTERY_POINT], AX



;2- SETTING UP AND LOADING THE FAT
MOV AX, 1
MOV BX, TEMP                            ;THE TEMP STORAGE FOR THE DATA WILL BE READED OR LOADED
CALL LOG_TO_HTS
MOV AH, 2                       ;THE FUNCTION CODE FOR LOADING ROOT DIR.
MOV AL, 9                       ;THE SIZE OF THE ROOT DIR. THE ROOT DIR. = 14 AND WE WANT TO LOAD IT ALL SO AL=14
PUSHA                           ;TO BE ABLE TO RETRY TO LOAD ROOT DIR. IF INT 13H FAILED
LOAD_FAT:
INT 13H
JNC LOAD_FAT_DONE                       ;IF WE ARRIVE HERE, THATS MEAN THAT THE FAT LOADED SUCCESSFULLY
CALL RESET_DRIVE                        ;RESET FLOPPY FUNCTION CALL
JMP LOAD_FAT                            ;RETRY IF INT 13H FAILED


LOAD_FAT_DONE:                          ;IF LOADING FAT DONE SUCCESSFULLY, WE WILL BE HERE
MOV AH, 2
MOV AL, 1 
PUSH AX

LOAD_SECTOR:                            ;ROOT DIR. GIVES US A DATA SECTOR AND WE WANT A LOGICAL SECTOR, WE WILL DO IT HERE
MOV AX, WORD [ENTERY_POINT]
ADD AX, 31                      ;31 ADDED TO DONE THE CONVERTION

CALL LOG_TO_HTS                         ;COVERTS THE LOGICAL SECTORS INTO HEAD TRACK SECTORS
MOV AX, 2000H
MOV ES, AX
MOV BX, WORD[OFFSET_]
POP AX
PUSH AX

INT 13H
JNC GET_NEXT
CALL RESET_DRIVE
JMP LOAD_SECTOR

GET_NEXT:
MOV AX, [ENTERY_POINT]
MOV DX, 0
MOV BX, 6
MUL BX
MOV BX, 4
DIV BX
MOV SI, TEMP
ADD SI, AX
MOV AX, WORD[SI]

OR DX, DX
JZ EVEN

ODD:
SHR AX, 4
JMP SHORT COMP_SECTOR

EVEN:
AND AX, 0FFFH

COMP_SECTOR:
MOV WORD [ENTERY_POINT], AX
CMP AX, 0FF8H
JAE END
ADD WORD[OFFSET_], 512
JMP LOAD_SECTOR

END:
;MOV SI, KERNEL_LOADED_MSG
CALL ECHO

CALL WAIT_FOR_KEY

POP AX
MOV DL, BYTE[BOOT_DEVICE]
JMP 2000H:0000H

OFFSET_                 DW      0
ALL_SECTORS             DW      18
FACES                   DW      2
ENTERY_POINT                    DW      0
;FAILED_TO_LOAD_KERNEL                  DB      "Error, Cannot Load The Kernel. Booting Process Aborted;",0
BOOT_DEVICE                             DB              0
FILE_NAME               DB      "KERNEL  BIN"
;WELCOME_MSG                             DB              "Litesoft bootloader  Copyright (C) 2012-2016 By Mohamed El Sayed;",0
;KERNEL_LOADED_MSG                       DB              "Kernel Loaded, Press Any Key To Continue...",0
TIMES   510 - ($-$$)    DB      0               ;LOOK FOR EVERY SINGLE EMPTY BIT AND FILL IT WITH ZERO
                                                        ;TILL THE BOOTLOADER SIZE BE 512 BYTE
DW  0xAA55                                          ;THE BOOT SIGNETUARE, ALWAYS THE SAME

TEMP:                           ;HERE IN BYTE 513 WE HAVE SOME MEMORY THAT WILL NOT BE EXECUTED
;AND WE CAN USE IT AS A TEMP MEMORY

Если вы сгенерируете boot.bin из этого кода и поместите его в образ дискеты и используете команду для отображения информации о типе файла:

file floppy.flp

Это должно произвести что-то вроде этого, если это сработало:

floppy.flp: , смещение кода 0x99+3, OEM-ID "mkfs.fat", корневые записи 224, секторы 2880 (объемы ‹=32 МБ), секторы/FAT 9, секторы/дорожка 18, серийный номер 0x2d7e5a1a, без маркировки, FAT (12 бит), затем FAT

Если вы получите аналогичный вывод, его можно будет смонтировать с помощью команды mount.


Как вы могли заметить, данные в EBPB/BPB можно использовать для навигации по файловой системе FAT12.

person Michael Petch    schedule 30.08.2016
comment
ваш код помогает с проблемой монтирования, но я столкнулся с другой проблемой при попытке загрузить образ дискеты с помощью qemu. Ошибка: «Ошибка загрузки: не удалось прочитать загрузочный диск» - person Moe; 31.08.2016
comment
Могу сказать, что ваш код загружается на QEMU, но работает некорректно. Он закончится на Boot failed : Could not read the boot disk', но он попытался запустить ваш код. PS: я получаю эту ошибку, только если я использую опцию -hda для жестких дисков. Вы должны использовать -fda для образов дискет. Я взял ваш код и просто изменил MAIN, чтобы он печатал символ в верхнем левом углу дисплея, а затем сделал cli и hlt и работал, как и ожидалось. Кажется, в вашем коде есть что-то (ошибка), заставляющее его продолжать цикл перезагрузки, когда он продолжается и не может найти другой загрузочный носитель. - person Michael Petch; 31.08.2016
comment
Эта ошибка выходит за рамки этого конкретного вопроса. - person Michael Petch; 31.08.2016
comment
Отладка загрузчиков в реальном режиме, вероятно, проще в Bochs благодаря встроенному отладчику, который довольно хорошо справляется с отладкой в ​​реальном режиме. - person Michael Petch; 31.08.2016
comment
Еще один тест, который я провел, заключался в том, чтобы раскомментировать код печати WELCOME_MSG в MAIN. Он печатал приветственное сообщение в верхней строке дисплея, пока загрузка продолжалась. Ваш код очистки экрана на самом деле не работает. Изменение видеорежимов на видеорежим, в котором вы уже находитесь, часто ничего не дает. - person Michael Petch; 31.08.2016
comment
@Kordy Если вы хотите использовать прерывание BIOS, чтобы очистить (с атрибутом 7 белое на черном) отображение в текстовом режиме 80x25 (лично я бы написал прямо в видеопамять), вы можете сделать это следующим образом CLEAR: mov ax, (6<<8)|0 mov bh, 7 xor cx, cx mov dx, (24<<8)|79 int 0x10 ret. xor cx,cx устанавливает CX в ноль (занимает меньше места, чем mov). Int 10h/ah=06h — это прокрутка вверх Видеосервис БИОС - person Michael Petch; 31.08.2016
comment
@Micheal Petch Я использую эту команду для запуска QEMU sudo qemu-system-i386 -fda floppy.flp, но она выдает другую ошибку. загрузчик сказал, что ядро ​​​​не найдено, хотя я уверен, что правильно смонтировал его на floppy.flp, как вы сказали - person Moe; 01.09.2016
comment
Скорее всего файл был на диске, но у вас ошибка с поиском kernel.bin в таблице FAT. Трудно сказать, не видя код, который вы на самом деле используете сейчас, но это, вероятно, будет другим вопросом. Именно здесь можно использовать BOCHS и его внутренний отладчик для пошагового выполнения 16-битного кода реального режима, если это необходимо. Вы можете наблюдать, что происходит, инструкция за инструкцией, и просматривать значения в регистрах и памяти. - person Michael Petch; 01.09.2016