Тема не совсем про bximage. Обычно подключают образ, созданный при помощи bximage, к эмулятору и уже в нем инсталлируют в образ все, что надо. bximage просто создает чистый бинарный файл определенного размера.
Ну да, это я понял, в принципе я могу скажем, подключить программу загрузки, просто указав в настройках бокса нужный com-файл, но тогда получается диск размером 512 байт и соответственно там будет только одна программа загрузки. Хотелось бы узнать как имеенно инсталлировать boot-сектор и другие файлы ос в образ, созданный с помощью bximage ? Или есть ли альтернативные варианты создания образов ос для бокса? Как я видел выше, есть пример для создания образа ос для флоппика, подойдет ли он для создания образа ос на основе жесткого диска или флешки, а не флоппика?
Eugene22 bximage создаёт *.img файл. Это простой бинарный файл который имеет размер кратный размеру сектора. По умолчанию размер сектора равен 512. Также для совместимости CHS размер файла кратен этим числам. CHS - способ адресации в котором адрес задаётся при помощи указания цилиндров, головок, секторов. Расширение никак не влияет на структуру. Поэтому в разных эмуляторах и программах может отличаться. Обычно расширения файлов такие *.img - образ жёсткого диска *.ima - образ дискеты Отличаются образы дискет и жестких геометрией, а именно тем что у дискет должно быть определённое число головок цилиндров и секторов. Когда как у жёсткого выбор этих значений богаче. Для того чтобы образ стал загрузочным на него надо записать загрузочный сектор. Сделать это можно различными средствами. Удобнее наверно написать свою программу. Которая в целевой образ записывает сектор - первые 512 байт при этом не изменяет служебные поля. Для первых экспериментов хватит и 16-тиричного редактора такого как WinHex. Загрузочный сектор для дискет и жёстких отличается структурой. Признаком того что сектор c LBA=0 является загрузочным является сигнатура по смещению 510=55h и по смещению 511=0AAh (по смещению считаются от 0). BIOS проверяет эту сигнатуру и если видит её то выполняет загрузку. В BIOS Bochs можно отключить проверку. Для образа дискеты важно присутствие структуры BPB. Для жёсткого ограничений нет. Некоторые BIOSы берут геометрию дискет из BPB поэтому важно когда ты будешь менять первые 512 байт в твоём образе дискеты чтобы BPB сохранялся. Когда ты создаёшь образ диска в bximage то ты указываешь. Это будет жёсткий диск или мягкий(дискета) Floppy - в пер с английского означает мягкий. MBR, BootRecord я записываю при помощи WinHex. Свою программу пока не делал. По поводу файлов. Для записи файлов надо понимать какую структуру имеет образ диска. Ограничений по логической структуре жесткого диска и его образа нет. Автор волен выбирать сам. Если брать классическую, то в образ будет отформатирован в одну из известных файловых систем (ФС). Для работы с FAT могу посоветовать WinImage и UltraISO. Правда лучше будет если ты опять таки сделаешь свою утилиту. В Линуксе и Юниксе всё проще. Образ с любой из распространенных ФС легко монтируется. И ты можешь записывать на него файлы обычными дисковыми утилитами. А запись сектора можно сделать при помощи команды "dd".
Это зависит от ОС, которую ты инсталлируешь. Ты должен в эмуляторе запустить программу установки этой ОС, загрузившись с другого носителя/образа. В случае установки моей оси на абсолютно чистый образ я, например, выполняю примерно такие действия, используя загрузочный диск DOS: fdisk format setupmbr setupldr copy Естественно, есть: OSDev Wiki и др. Хотя создание образа с таблицей разделов может оказаться не самым легким делом. mkfloppy.inc для создания образа жесткого диска использовать нельзя (можно попробовать сделать образ для флешки, если ты будешь ее использовать в "режиме флоппика"). Я сейчас доделываю включаемые файлы для создания образа жесткого диска/флешки с одним или даже несколькими разделами (!!!), содержащими FAT12 или FAT16. Если тебе файловая система не нужна вообще, то такой образ (все равно, с таблицей разделов или без) сделать не сложно. Все зависит от цели. Твой загрузчик и прочие файлы рассчитаны на какую/какие ФС?
Pavia, Phantom_84, спасибо за ответы, буду разбираться. Пока не на что не расчитаны, в принципе и файлов пока нет. Есть только собственно начальный загрузчик, так как у меня возникли некоторые проблемы связи загрузчика с другими файлами. В идеале хотелось бы самому написать какое-нибудь подобие файловой системы, а пока - как получится.
Если поддержки ФС пока нет ни на коком уровне, то образ диска сделать в fasm'е элементарно. 1) без таблицы разделов: Код (Text): macro align value { db value-1 - ($ + value-1) mod (value) dup 0 } HEADS = 16 SPT = 63 file "boot.bin",512 ; твой загрузчик file "module1.bin" ; твой первый файл align 512 ... file "moduleN.bin" ; твой N-ый файл align 512 align HEADS*SPT*512 2) с таблицей разделов: Код (Text): macro align value { db value-1 - ($ + value-1) mod (value) dup 0 } PART_STATE = 80h PART_TYPE = 80h HEADS = 16 SPT = 63 file "mbr.bin",440 ; любой "стандартный" MBR-загрузчик db ?,?,?,?,0,0 db PART_STATE,1,1,0 db PART_TYPE,HEADS-1,(CYLINDERS-1) and 300h shr 2 + SPT,(CYLINDERS-1) and 0FFh dd SPT,(CYLINDERS*HEADS-1)*SPT db 510-$ dup 0 dw 0AA55h rb SPT*512-$ file "boot.bin",512 ; твой загрузчик file "module1.bin" ; твой первый файл align 512 ... file "moduleN.bin" ; твой N-ый файл align 512 align HEADS*SPT*512 CYLINDERS=$/(HEADS*SPT*512)
Phantom_84, я попробовал использовать первый код - где без файловой системы, на выходе у меня создается файл c расширением bin, но при запуске бокс не находит загрузочного устройства - No bootable device. Не знаю, может я на фасме неправильно программу написал - я первый день работаю с фасмом, раньше только с масмом работал Программа выглядит так Код (Text): jmp Begin macro align value { db value-1 - ($ + value-1) mod (value) dup 0 } HEADS = 16 SPT = 63 Begin: file "Eboot.exe",512 ; загрузчик align HEADS*SPT*512 Программа загрузки рабочая, что я делаю не так?
Второй тоже без файловой системы. "jmp Begin" убери - это все должно быть внутри "Eboot.exe" (exe? Надеюсь, это чистый программный код!)
Phantom_84, еще один вопрос - сейчас пытаюсь подгрузить еще один файл из загрузчика то есть программа приняла вид Код (Text): macro align value { db value-1 - ($ + value-1) mod (value) dup 0 } HEADS = 16 SPT = 63 Begin: file "eboot.com",512 ; загрузчик file "Kernel.com" ; твой первый файл align 512 align HEADS*SPT*512 Как я понимаю, Kernel.com попадает во 2 сектор нулевого цилиндра нулевой головки? И еще создаваемый образ рассматривать как жесткий или как гибкий диск - то есть что в регистр dl должно быть при чтении сектора?
Верно. Хотя лучше сразу перейти к линейной адресации (LBA). Линейный номер сектора (а также при необходимости размер) можно вычислять тут же: Код (Text): align 512 ; если не уверен в правильности выравнивания тек. позиции kernel_sect=$/512 file "kernel.com" align 512 kernel_size=$/512-kernel_sect ; размер в секторах, если нужен Эти значения ты можешь использовать в загрузчике. Например, можно определить структуру для хранения местоположения и размера твоего ядра в строго определенном месте (по определенному смещению) внутри загрузчика и делать так: Код (Text): kernel_desc equ 40h ; к примеру смещение 40h store dword kernel_sect at kernel_desc store word kernel_size at kernel_desc+4 Вообще ты вроде собирался делать образ для жесткого диска. В этом случае его номер практически всегда будет равен 80h. Ты можешь также определить байтовую ячейку для хранения этого номера по строго определенному смещению внутри загрузчика (так делает большинство загрузчиков) и в случае необходимости его менять (без перекомпиляции загрузчика). Ты также можешь использовать номер загрузочного диска, который передает твоему загрузчику BIOS в регистре dl. Это будет работать для жестких дисков и флешек с произвольным номером (так делают прогрессивные загрузчики). При этом ячейку для хранения номера диска внутри загрузчика можно сохранить (на случай использования глючного BIOS, не передающего номер диска в dl) и использовать какое-либо специальное значение для этой ячейки, к примеру 0xFF, указывающее на то, что номер диска нужно брать от BIOS (так делает GRUB).
Про LBA я немного читал, но решил пока идти от простого к сложному. Прочитать следующий сектор - то есть ядро вроде удалось, но возникла проблемка - ядро просто представляет программу вывода сообщения, но вот сообщение выводится совсем не теми символами, которыми бы надо. Причем сообщения загрузочного сектора отображаются как надо. Причем делал как на масме так и на фасме - результат один и тот же. Код загрузочного сектора Код (Text): org 7c00h start: cli ;запрещаем прерывания xor ax,ax ;обнуляем регистр ах mov ds,ax ;настраиваем сегмент данных на нулевой адрес mov es,ax ;настраиваем сегмент es на нулевой адрес mov ss,ax ;настраиваем сегмент стека на нулевой адрес mov sp,07C00h ;сегмент sp указывает на текущую вершину стека sti ;разрешаем прерывания ;очищаем экран mov al, 02h mov ah, 00h int 10h call GetCursorPos ;получаем позицию курсора mov bp, msg ; Загрузка mov cx, 13 call print ;Вывод на экран строки msg add dh,1 ;переходим на одну строку ниже call SetCursorPos mov bp, Con ; Загрузка mov cx, 23 call print Char: call Char_in cmp al, 0Dh ;Если нажимаем на Enter, то переходим к загрузке ядра jz Kernel jmp $ Kernel: mov ax,0000h mov es,ax mov bx,8000h ; Entry Point - KernelSEG:100h mov ch,0 ;номер цилиндра - 0 mov cl,02h ;начальный сектор - 2 mov dh,0 ;номер головки - 0 mov dl,80h ;жесткий диск - 80h mov al,01h ;кол-во читаемых секторов -1 mov ah,02h int 13h jmp 0000:8000h ;===================== Подпрограммы =================================== print: ;в регистре bp - строка, в регистре cx - длина этой строки mov bl,04h ;в регистре bl- атрибут mov ax,1301h int 10h ret ;---------------------------------- GetCursorPos: ;получаем текущее значение курсора функиция 3h прерывания 10h ; в bh страница mov ah,3h xor bh,bh int 10h ret ;---------------------------------- SetCursorPos: ;установка курсора : функция 02h прерывания 10h mov ah,2h xor bh,bh int 10h ret ;---------------------------------- Char_in: ;ожидание нажатой клавиши : функция 10h прерывания 16h mov ah,10h int 16h ret ;===================== выводимые сообщения===================== msg db 'OS Loading...',0 Con db 'Press Enter to Continue',0 times(512-2-($-07C00h)) db 0 db 055h,0AAh ;сигнатура, символизирующая о завершении загрузочного сектора Код как бы ядра, сообщения которого выводятся неправильно Код (Text): message: mov ax, 0002h int 10h mov bp, mg mov cx, 15 mov bl,08h xor bh,bh mov ax,1301h int 10h mg db 'Hello Eugene....',0 Вроде все правильно, но почему то выходит не то. И второй вопрос - какой диапазон памяти можно использовать для загрузки ядра в регистры es:bx?
1. По поводу первого вопроса учи макрокоманду org. 2. Ну тут 3 вопроса. Для загрузки ядра можно использовать всю доступную память. Можешь считать из переменных биоса размер базовой памяти, для определения доступной в первом мегабайте памяти за вычетом таблицы прерываний и самих переменных биоса ну и ещё 100h резервируем. т.е. 0 по 6FF включительно считай что занято. А для определения того что выше использовать прерывания биоса. Int 15 SMAP и другие функции. PS. Скачай книгу про Ассемблер и почитай.
Pavia прав (org 8000h в помощь; это корректнее называть директивой, а не макрокомандой). Хотя, как вариант jmp 800h:0 в загрузчике или jmp 800h:next_pos_disp в "ядре". Но я предпочитаю по минимуму работать с сегментными адресами реального режима, поэтому использую jmp 0:next_pos_disp в ядре - это позволяет оставаться в рамках линейной адресации и использовать код реального режима размером до 32 кб. startup.asc Код (Text): section startupcode16 { Startup: xor bx,bx cli mov ss,bx mov sp,7C1Ch sti ; Сохраняем в стеке параметры, полученные от загрузчика. label .FSFileSize dword at 7C1Ch-4 push cx push ax push bx push dx jmp 0:@f ... @@: ... } kernel.asc Код (Text): org 8000h put startupcode16,initcode16,startupdata16,initdata16 virtual rb 10000h-$ end virtual ... Я файл ядра (и еще один дополнительный файл) первоначально загружаю в базовую память. Мои загрузчики используют int 12h для определения размера доступной базовой памяти (переменные BIOS должны дать аналогичный результат).
Еще вариант для com-файла (стартовое смещение 100h, т.е. нужно использовать org 100h): jmp 7F0h:100h в загрузчике или jmp 7F0h:next_pos_disp (имеется в виду 100h+) в "ядре".
Спасибо, более менее понятно становится. org 8000h - все работает, а jmp 800h:0 - этот вариант не прокатывает. По поводу диапазона адресов, просто в этой теме - http://www.wasm.ru/forum/viewtopic.php?id=30307 - говорится, что используемая оперативная память для ос и программ располагается в диапазоне 500h-9FFFFh, в то же время у Криса Касперски я прочитал - мне просто непонятно, почему у него нижняя граница 0080:0067h, просто интересно, какие допустимые значения можно использовать для регистров es и bx
Не прокатывает, потому что ты, видимо, делаешь com-файлы (org 100h). Для чистого бинарника с нулевым стартовым внутрисегментным смещением прокатывает. Для com-файлов я привел другой вариант (см. последний пост). Там много чего говорится. Но я по прежнему придерживаюсь своего мнения: - "Про память ниже первого мега рассказали подробно: начиная с 500h и до значения, возвращаемого функцией BIOS int 12h в килобайтах". - "9FC00h-9FFFFh - может быть и больше! - расширенная (дополнительная) область данных BIOS, нижнюю границу которой как раз и можно получить с помощью int 12h". - "В принципе в защищенном режиме, если работа BIOS полностью остановлена, то можно использовать и IVT, и BDA, и EBDA, но я бы не советовал это делать, потому что BIOS может работать даже тогда, когда это казалось бы невозможно, например, в режиме SMM". Мне тоже непонятно, откуда это взялось. Я всегда использовал базовую память, начиная с адреса 500h, и не имел никаких проблем. Можешь взять за основу адрес 600h - так делают очень многие. Можешь еще сильнее перестраховаться. Т.к. эти адреса обычно являются дном стека у первичных загрузчиков (хотя некоторые mbr- и первичные загрузчики их все-таки используют) и инициализационного кода ядра, до они практически не используются, а в своем "ядре" можешь вообще не использовать/не изменять первую страницу (4 кб) физической памяти.