В общем, объясняю ситуацию. Сделал утилиту, которая создаёт образ FAT16-диска. Сделал тестовую утилиту, которая читает бутсектор и выводит на экран (ну всё положено, с местом под FAT и BPB). Читаем через функцию 0x42 int 0x13. Компилю бутсектор - первые 0x3c байт - это jmp + заголовок FAT (нули) + BPB (тоже нули). 1. Создаю образ (первые 0x3c байт утилита прописывает в соответствии с создаваемой ФС FAT16, как и ожидалось). Записываю образ на флешку, начиная с 0 сектора, и бутаюсь. Вместо корневого каталога (чётко прописан сектор - 0x41) читается какая-то ерунда. 2. Пишу вместо 0 сектора скомпилированный boot, где нули вместо заголовка FAT и BPB. Бутаюсь с флешки, рутовый каталог читается как надо. При этом, к первым 0x3c байтам тестовый код бутсектора вообще не ссылается. Я уже весь код пересмотрел, перечитал. Эмуляторы (BOCHS, QEMU) отрабатывают корректно и в первой, и во второй ситуации. А вот BIOS не хочет. Может, кто-нибудь разъяснит, почему в первом случае BIOS отрабатывает некорректно, а во втором - корректно? Вот код: Код (Text): ; Some Constants use16 org 0x7c00 BOOT_SECTOR_SIZE = 0x200 FAT_LAST_CLUSTER = 0xfff8 ;------------------------------------------------------------------------------- ; Main Entry Point start: jmpBoot: jmp fat_start_load jmp_dump: nop OEMName: db 0,0,0,0,0,0,0,0 BytesPerSec: dw 0 SecPerClus: db 0 RsvdSecCnt: dw 0 FATsCount: db 0 RootEntries: dw 0 TotalSectors: dw 0 MediaType: db 0 FATSize: dw 0 SectsPerTrack: dw 0 HeadsCount: dw 0 HiddenSectors: dd 0 TotalSectors32: dd 0 DrvNum: db 0 Reserved: db 0 BootSig: db 0 VolumeId: db 0,0,0,0 DiskLabel: db 0,0,0,0,0,0,0,0,0,0,0 FileSystem: db 0,0,0,0,0,0,0,0 fat_start_load: ; Change Segment Registers cld cli xor ax, ax mov ss, ax mov ds, ax mov es, ax mov sp, start sti ; Try to read data xor dx, dx mov ax, 0x41 mov bx, disk_buffer mov cx, 2 call read_sectors_lba ; Output buffer mov si, disk_buffer mov cx, 512 output_loop: lodsb test al, 0xf0 jnz cont_loop mov al,' ' cont_loop: pusha xor bx, bx mov ah, 0x0e int 0x10 popa loop output_loop end_loop: jmp $ ; Read Sector In LBA Mode ; DX:AX = sector lba number ; ES:BX = buffer address ; CX = sector count read_sectors_lba: pusha ; Fill Disk Address Packet mov si, dap ; DS:SI -> dap mov [dap_lba], ax ; dap.lba = ax mov [dap_lba+2], dx ; dap.lba+2 = dx mov [dap_buf_off], bx ; dap.b_off = bx mov ax, es mov [dap_buf_seg], ax ; dap.b_seg = es mov [dap_count], cx ; dap.count = cx ; Call Read Function Until Success retry_read: mov ah, 0x42 mov dl, 0x80 int 0x13 jnc ok_read pusha xor bx, bx mov ah, 0x0e mov al, '!' int 0x10 popa jmp retry_read ok_read: popa ret ;------------------------------------------------------------------------------- ; Disk address packet SearchEntry: db 'XLOAD COM' FATSector: dw 0xffff dap: dap_size: db 0x10 dap_reserved: db 0 dap_count: dw 0 dap_buf_off: dw 0 dap_buf_seg: dw 0 dap_lba: dd 0, 0 CluSize: dw 1024 ; Variable for cluster size store FirstCluster: dw 32+41 ;------------------------------------------------------------------------------- ; Align end to 512 bytes and put boot signature times (BOOT_SECTOR_SIZE-2-VOLUME_INFO_SIZE-($-$$)) db 0xff vol0_desc: dd 0,0,0,0 ; Volume 0 Descriptor vol1_desc: dd 0,0,0,0 ; Volume 1 Descriptor vol2_desc: dd 0,0,0,0 ; Volume 2 Descriptor vol3_desc: dd 0,0,0,0 ; Volume 3 Descriptor dw BOOT_SIGNATURE disk_buffer:
А учитывается, что на флешках обычно существует MBR и при записи образа в логический диск \\.\X: сектор образа 0x41 попадает в совсем другой сектор физического диска? При тестировании в Bochs и qemu, возможно, образ использовался как таковой, а при физической записи на флешку это нужно учитывать.
В данном случае вам предоставлен код MBR. В 0x41-ом секторе я 100% знаю, какие находятся данные. Код MBR не выводит их, если первые 0x3c байт - не нули (исключая, конечно, jmp).
SadKo Сразу после jmp идет инфо о носителе затем код загрузчика (на него то jmp и нужен) и в конце таблица разделов, например, для дискеты 3.5" номер лог. сектора вычисляется по формуле (см. справочник Кулакова) и не как у флешки. Это я к тому - попробуйте использовать старый-добрый сервис/прерывание БИОС с использованием C:H:S
SadKo Ахтунг!!! Вычисляйте адреса в своём коде примерно так: Код (Text): call label_base label_base: pop eax add eax, dap_buf_seg - label_base ; и теперь в eax будет правильный адрес для переменной/метки dap_buf_seg
А чем это лучше, если я просто задам org 0x7c00? Сорри, в коде не указал, что эта директива есть. Исправлю.
Старый добрый сервис работает у меня на дискете. Моя же задача - как раз написать загрузчик с исользованием расширенного дискового сервиса. Мало того, я не знаю параметров CHS моей флешки.
SadKo 1. Адреса лучше программно находить, чем в коде их вписывать 2. Очень выручит Вас книга В. Кулакова http://www.pcports.ru/files/lib/kulakov.rar
Спасибо, эта книжка у меня есть. Так всё же, объясните мне этот факт: код одинаковый, а вот bios в одном из случаев не хочет грузить.
Не знаю... ну, может LBA в БИОС отключен? - Проверьте это три раза (один раз - это секс, три раза -это уже наука ) и оставьте как есть
Подтверждено эмпирически . Если ситуация 1 - всё ОК, если ситуация 2 - полная лажа. В 100% случаев (а проверял я не раз и поочереди).
Может, утилита при создании образа немного портит бутсектор и не только изменяет первые 0x3c байт, но и по ошибке перезаписывает что-то в середине? Типа какого-нибудь выхода за границы какого-нибудь массива? Выглядит малоубедительно, но ошибки чтения в коде BIOS, появляющиеся только при ненулевых значениях в MBR - это уже что-то из области ненаучной фантастики. Кстати, несколько странно, что один и тот же сектор планируется и как MBR, и как BPB-содержащий - всё-таки таблица разделов не должна входить в указываемый самой собой раздел. Но BIOS вообще не в курсе существования разделов, так что к заданному вопросу это отношения не имеет.
Нет, я в этом уверен - лично сверял . Вот и я тоже в недоумении: какое дело Биосу, что там в MBR творится? Это всего лишь следствие того, что я пока не написал MBR. Поэтому просто решил из флешки сделать диск без разделов, соответственно MBR == SMBR. А место под Volume Table всё равно надо оставлять (для extended-разделов). Я хотел проверить, как работает ФС. Сейчас заступорился на чтении сектора.
Значит, последние мои наблюдения: попытался вывести нулевой сектор диска. Что самое забавное, bios мне выдал содержимое нулевого сектора жёсткого диска, а не flash. Спрашивается - как можно узнать номер диска (который будет потом помещаться в dl), с которого производится загрузка?
Его BIOS помещает в dl непосредственно перед передачей управления бутсектору. Хотя вообще-то обычно BIOS'ы стараются делать так, чтобы идентификатор загрузочного диска был бы всегда 80h (или 0 для дискеты), перемешивая "настоящие" идентификаторы - для совместимости (стандартный MBR, например, всегда считает, что загрузка происходит с диска 80h).
Итак, шоу начинается... Случай 1 и случай 2, как водится. Случай 1 - состояние регистров: Код (Text): # dx cx si di 1 0000 0001 0003 0000 2 0080 0001 0005 0000 И как это называется???
SadKo Все верно. Флешку можно воспринимать как флопи и как диск. Зависит он настройки в биосе. А еще есть такая вещь как поддержка функции 42h ее лучше использовать для больших дисков а с малыми она может и не работать.
SadKo 1. Я уже, правда, повторяюсь, но всёже: когда настанет время загрузить стандартный MBR (а у него тоже base = 0000:7C000h) и передать ему управление, Вы, тогда вспомните и обо мне, т.е. о моём 2 посте в данной теме. Ведь компилять свой код неудобно, например, с ORG (7С00h + 200h) и с самого начала и до переноса "самого себя" в новое место бояться использовать абсолютные адреса своих данных. 2. По вопросу о разных значениях в DL номера привода из-за инфы о носителе в MBR могу сказать только одно: если пишите свой MBR на винт, то используйте 80h для ссылки на самого себя, а если на сменный носитель – 0. Хм... если что, то все ошибки можно всегда списать на Большой адронный коллайдер!
Ну вы меня уж совсем за идиота не держите. MBR копирует себя обычно адресом 0x200 ниже, чем 0x7c00, после чего передаёт туда управление. BIOS вообще должно быть до лампочки, что за код и данные находятся в MBR или SMBR. Она должна передать и успокоиться, ждать либо int 0x18, либо int 0x19. Вот в том-то и дело, что не 0. И не 0x80. Надо с разработчиками Award BIOS'а, наверное, связаться.