Создание своего загрузчика ОС

Тема в разделе "WASM.BEGINNERS", создана пользователем unregistered, 16 ноя 2006.

  1. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Доброго времени суток.

    Делаю лабу, задание - загрузить процесс и передать ему управление...
    Народ делает под DOS'ом (o.O), но это неинтересно, я решил грузиться с дискетки...

    Для лабы мне достаточно кода MBR, kernel, process1 (тестовый процесс)
    код в MBR "переежжает" в 0000:7C00, грузит kernel в память, и передает ему управление...
    kernel грузит process1, запускает его, принимает управление и зацикливается ( :) ),
    этого достаточно для сдачи лабы. В следующей лабе будет простая многозадачность.

    В качестве файловой системы использовал дорожки, т.к. кода у меня мало,
    и заведомо знаю, что 9 кб хватит для каждой части ос и для процесса.

    Для создания образа дискетки делаю image на 1474560 байт, и на сях "прожигаю" туда com-файлы:
    MBR - по нулевому смещению, нулевая дорожка
    kernel - 2400h смещение, т.е. первая дорожка
    process1 - 4800h, 2я

    Далее, что я пытаюсь делать в MBR:
    Код (Text):
    1.     .model  tiny
    2.     .code
    3.  
    4.     org 100h
    5. entry:
    6.     ; цель MBR - загрузить ядро в память
    7.     ; и передать ему управление
    8.     ; ядро грузим в 0000:0600, сразу
    9.     ; после таблицы прерываний
    10.  
    11.     ; каждый com-файл занимает не более
    12.     ; одной дорожки, т.е. 9 килобайт
    13.  
    14.     ; после перемещения кода из MBR в 0000:7C00
    15.     ; состояние регистров будет слелующее:
    16.     ; CS = 0
    17.     ; IP = 7C00
    18.     ; DL - номер накопителя, его передаем в функцию чтения ядра с диска
    19.  
    20.     mov al, 12h     ; читаем 18 секторов == 1 дорожка
    21.     mov dh, 00h     ; используя первую головку
    22. ;   mov dl, 00h     ; диск, откуда грузимся, его номер нам скажет BIOS
    23.     mov ch, 00000000b   ; номер цилиндра (дорожки), kernel на 1й дорожке
    24.     mov cl, 10100000b   ; номер сектора + кусок номера
    25.                 ; цилиндра (старшие 2 байта)
    26.     mov bx, 0000h   ; адрес,
    27.     mov es, bx      ; куда читать
    28.     mov bx, 0600h   ; ядро
    29.     mov ah, 02h     ; читаем ядро
    30.     int 13h
    31.  
    32.     jc  loop1
    33.  
    34.     ; сколько прочитано секторов
    35.     ;mov    al, ah
    36.     add al, '0'
    37.     mov ah, 09h
    38.     mov bh, 00h
    39.     mov bl, 01h
    40.     mov cx, 0001h
    41.     int 10h
    42.  
    43.     ; подготовка передачи управления ядру
    44.  
    45. loop1:
    46.     jmp loop1
    47.  
    48. end entry
    Проблема у меня в этих строчках :dntknw:
    mov ch, 00000000b ; номер цилиндра (дорожки), kernel на 1й дорожке
    mov cl, 10100000b ; номер сектора + кусок номера

    Как правильно задавать дорожки? http://www.codenet.ru/progr/dos/int_0012.php - тут очень содержательно написано :dntknw:((

    ps: jc loop1 используется для отлова ошибки, т.е. если все прошло успешно, на экран выведется буковка...

    заранее спасибо
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    хм, а в чё загвоздка?
    в ch клади номер дорожки, в cl - 0.
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    unregistered
    А вы уверены, что хотите прочесть 32ой сектор 512ого цилиндра на нулевой головке? Кажется, дискет с такой геометрией не бывает...
     
  4. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Mika0x65
    дык он и грит что проблема с этом =)
     
  5. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    ошибка
    org 100h
    нужно
    org 7С00h
    А то все смещения будут расчитаны не верно.

    Если не ошибаюсь, то в cl должен быть 1. А в ch указываешь номер дорожки.
     
  6. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Pavia

    org 7C00h не скушает TASM

    > Если не ошибаюсь, то в cl должен быть 1. А в ch указываешь номер дорожки.
    Попробую... просто немного непонятно, как руководствоваться этим:
    Код (Text):
    1. +5-4-3-2-1-0-9-8-7-6-5-4-3-2-1-0+
    2. ¦c c c c c c c c C c S s s s s s¦
    3. +-+-+-+-+-+-+-+-¦-+-+-+-+-+-+-+-+
    спасибо за ответы :)
     
  7. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Это у тебя регистр CX сверху пронумерованы биты от 0 до 15.
    CX состоит из двух частей {CH,CL}
    Где:
    CH старшые 8 бит 8-15
    CL младшие 8 бит 0-7

    При обращении к жесткому диску (CH) содержит 8 младших бит номера
    дорожки, два старших бита размещаются в битах 7 и 6 (CL).
    Вот из Tech Help скопировал.
    Код (Text):
    1. 02H read sectors
    2.     Input: DL = drive number (0=drive A...; 80H=hard disk 0; 81H=hard disk 1)
    3.            DH = read/write head number
    4.            CH = track (cylinder) number (0-n) <═╗
    5.            CL = sector number (1-n) <═══════════╩══ See note below.
    6.            AL = sector count (no more than 1 cylinder's worth of sectors)
    7.            ES:BX => caller's buffer address
    8.            0:0078 => Diskette Parameter Table  (for diskette operations)
    9.            0:0104 => Hard Disk Parameter Table  (for hard disk operations)
    10.   Output: Carry Flag=CY=1 if error occurred and disk error code in AH.
    11.           ES:BX buffer contains data read from disk
    12.  
    13.           Note: Sector values are 6-bits and Cylinder values are 10-bits:
    14.                  1 1 1 1 1 1
    15.                 ╓5┬4┬3┬2┬1┬0┬9┬8╥7┬6┬5┬4┬3┬2┬1┬0╖
    16.             CX: ║c c c c c c c c C c S s s s s s║
    17.                 ╙─┴─┴─┴─┴─┴─┴─┴─╨─┴─┴─┴─┴─┴─┴─┴─╜
    18.                                  ╚═╩═══> used as high bits of cylinder number
    TASM скушает org 7C00h C-латинская. Другое дело, что это нужно для MBR, а вот для COM нужен org 100h
    У тебя, правда пример простой, так что это себя пока никак не проявило. Но как только начнешь использовать глобальные переменные, начнутся проблемы с адресацией.
     
  8. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    у меня TASM не кушает 7C00h:
    Fatal: Cannot generate COM file : invalid initial entry point address

    Далее, при:

    cl=1, ch=1, в память по 0000:0600 попадают значения, из которых создается
    "пустышка" дискетки (т.е. нолики, или единичка, только что проверил для уверенности)
    cl=1, ch=0, в память по 0000:0600 корректно попадает код из MBR

    магия? где мой кернель? :) может я неправильно прожигаю его на образ дискетки?
    kernel.com записывается в образ со смещением 2400h, т.е. 512 * 18 * trackNumber (равный 1му)

    ps: гоняю "ось" под bochs, позволяет сделать слепок состояния машины
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    To Pavia:
    Даже не смешно! Какие же это "ВСЕ" смещения? Я там не вижу ни одного.
    Возможно Вас смущают прыжки на loop1? В связи с тем, что переходы короткие, все будет рассчитано верно.
    To unregistered:
    К тому что уже сказано: я немного сомневаюсь по поводу чтения в 0000h:0600h. Было бы корректнее переписать свою прогу в памяти куда-нибудь в другое место, а kernel грузить в 0000h:7с00h. Плюс мелочи типа обнуления регистров mov'ом, а не xor'ом, например.
     
  10. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    l_inc
    То что расчитанно будет верно я не спорю. Но пусть привыкает делать правельно. Да TLink ругается на 7С00h если делать COM, но MBR это не ком. Так что при линковки стоит задать другое расширение выходного файла BIN, MBR, SYS и не будет проблем с линковкой.
    unregistered
    Так а головки, кто считать будет? =)
    Sector = (LBA mod SectorsPerTrack)+1
    Cylinder = (LBA/SectorsPerTrack)/NumHeads
    Head = (LBA/SectorsPerTrack) mod NumHeads
    Так что 2400h будет Sector=1 Cylinder=0 Head=1
    Код (Text):
    1.     mov    dh, 1        
    2.     mov    ch, 0           
    3.     mov    cl, 1
     
  11. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    To Pavia
    :)
    Не знаю на 100%, но не уверен, что в Tasm можно создать что-то более приближенное к бинарнику, чем com. Поэтому ИМХО удобнее всего все-таки устанавливать ORG 100h, чтобы уважить tlink, а потом, при необходимости, прибавлять 7b00h ко всем смещениям.
     
  12. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Pavia
    оо, спасибо :))) работает! ядро загрузил, запустил, буковку на экран выплюнуло :) гуд

    управление передавал установкой CS:IP в 0000:0600, т.е. куда загружено ядро
    Код (Text):
    1. push    0000h
    2. push    0600h
    3. ret
    все, управление передали... вопрос - как передать управление, что бы я в com-программе мог использовать
    мною созданные данные? хотелось бы на экран выдавать не просто буковку, а строчечку. информативнее :)
    и как настроить стек? =/

    т.е. раньше, когда я баловался, в MBR делал так:

    Код (Text):
    1. mov    bp, offset msg
    2. sub    bp, 100h        ; это все
    3. add    bp, 7C00h       ; эквивалентно 7B00h
    очень хочется избавиться от подобного финта ушами.

    благодарю (:
     
  13. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    To unregistered
    "Финт ушами" лучше делать так:
    Код (Text):
    1. mov    bp, offset msg + 7B00h
    В результате на конечном коде ORG 100h и все корректировки смещений никак не отразятся (никаких сложений/вычитаний кодироваться не будет).
    Т.о. ORG 100h полностью сглаживается, но, тем не менее, он необходим для формирования com'а, и это становится его единственным назначением. Т.е. "финт ушами" виден исключительно в исходном коде (ИМХО не велика потеря), но бинарник совпадает с тем, который бы мы получили с указанием ORG 7c00h. Ну... или можно сменить компилятор (на fasm, например).
     
  14. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Про это я уже упоминал сто раз, чтобы линкер смог правельно расчитать смещения нужно задать базовый адресс. Делается это через org.

    Если COM и у него выставлена деректива org 100h
    Тогда делай так.
    Код (Text):
    1. push    0050h
    2. push    0100h
    3. retf
    Про данные в MBR я уже писал org 7C00h и это самый простой способ. Но можно через дальний переход подкаретировать базовый адресс так что бы CS=07B0h и DS выставить равным CS.

    Для com стек выставляешь так: база таже самая что и у кода, а указатель на конец сегмента.
     
  15. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    unregistered
    А попробуй как org 7c00h на фасме, скушает нет?
     
  16. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Pavia
    0050:0100 не проходит. странно, ведь 0050*10+0100==0600
    bochs мне пишет lock prefix unallowed, а если грузиться в реале, то железо вообще молчит, ну то понятно

    собственно, все махинации с адресами при передаче управления нужны для того, чтобы:
    1. не морочить голову при разработке тестовых процессов
    2. по человечески было написано :)

    еще один вопрос. LBA - Linear Block Address. В чем его мерять? Это мои смещения 2400h, 4800h, ...?
    Или номера секторов? Гугль на банальное "что такое LBA" не дал вразумительного ответа =/

    благодарю :)
     
  17. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    unregistered
    А моя ошибка нужно retf вместо ret
    LBA - линейный адресс сектора измеряется секторами то есть 12h,24h ... 12h(2400h/512d).
     
  18. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    С т.з. LBA все пространство секторов винчестера представлено в линейной последовательности, нумерация идет с нуля. "Формула", которую написал Pavia как раз переводит LBA адрес в CHS представление. Так что то, что скормил в эту формулу и есть LBA-адрес.
     
  19. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Только сейчас заметил, что опоздал на две минуты и двадцать восемь секунд :).
     
  20. unregistered

    unregistered New Member

    Публикаций:
    0
    Регистрация:
    16 ноя 2006
    Сообщения:
    10
    Фух, сдал =) Запуск процесса, передача управления, и прием управления через прерывание.
    Осталось две:
    - многозадачность. переключение процессов по прерыванию от клавиатуры.
    - синхронизация. разработка семафора.

    У меня возникло желание по окончании курса оформить это в виде нескольких статей, и разместить где-нибудь
    в инете. Что скажет общественность? :) Т.к. толковых туториалов очень мало... То, что нашел:
    Real HelloWorld
    Пишем игрушечную ОС
    Пишем игрушечную ОС. Копнем поглубже
    GLUKOS
    и http://www.codeproject.com/system/MakingOS.asp

    Все они или очень сложные, или простые, но плохо документированные. Последняя, на codeproject, наиболее понятная, но в ней тоже очень много косяков...