Вопрос касательно программирования MBR

Discussion in 'WASM.OS.DEVEL' started by drunken_cowboy, Sep 26, 2011.

  1. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    Доброе утро. Я в ассемблере, можно сказать, новичок и хочу освоить низкоуровневое программирование на примере своего загрузчика. Схема примерно такова: в MBR диска садится код, проверяющий наличие диска с определённым ID, а оригинальная MBR сохраняется в другой сектор и потом подгружается.

    Дабы не плодить множество файлов, я хотел код, который будет записан в MBR, записать, скажем, в инсталляторе, в отдельной секции, а потом просто скопировать на место MBR. Но инсталлятор на MASM32, поэтому вопрос такой: будет ли код, написанный под Win32 без использования 32-разрядных регистров, работать на таком уровне? Т.е. будет ли он тем же, как если бы я собирал его в отдельном com-файле под досом?

    Сам код для MBR:
    Code (Text):
    1.     org 7C00h                              
    2.                         ; Загрузим себя по другому адресу
    3.                         ; Но не весь код, а только с
    4.                         ; метки payload
    5.     cld
    6.     mov si, (payload + 7C00h)
    7.     mov di, 7D00h
    8.     mov cx, 200h
    9.     rep movsb                          
    10.                                    
    11.     jmp 0000:7D00h      ; far jump на копию нашего кода
    12.    
    13. payload:
    14.                         ; Чтение старой MBR из 8 сектора
    15.                         ; в режиме CHS
    16.                                
    17.     mov ax, 0201h           ; Номер функции & номер сектора
    18.     mov dl, 80h         ; С первого диска
    19.     xor dh, dh          ; Нулевой головки
    20.     mov cx, 0008h           ; Восьмой сектор нулевого
    21.                         ; цилиндра
    22.     mov bx, 7C00h           ; Читаем по смещению бывшего
    23.                         ; загрузчика 
    24.     int 13h
    25.  
    26.     ; Тут рабочий код, не забываем о 446 б. Мэйби есть смысл подгрузить ещё
    27.     ; кода
    28.    
    29.                         ; Прыгаем на оригинальную
    30.                         ; загрузочную запись
    31.     jmp     0000:7C00h
     
  2. Phantom_84

    Phantom_84 New Member

    Blog Posts:
    0
    Joined:
    Jun 6, 2007
    Messages:
    820
    Ты должен вставить бинарник в инсталлятор в каком-либо виде (например, как байтовый массив констант).

    То, о чем ты говоришь, возможно, но не целесообразно и потребует весьма специфических действий по пересчету смещений и т.п. Хотя в fasm'е это сделать не сложно:

    Code (Text):
    1. mbr:
    2.   org 7C00h
    3.   use16
    4.   ...
    5.   rb 7DB8h-$
    6.   org mbr+($-$$)
    7.   use32
     
  3. Pavia

    Pavia Well-Known Member

    Blog Posts:
    0
    Joined:
    Jun 17, 2003
    Messages:
    2,409
    Location:
    Fryazino
    Дело не в регистрах. А в системах декодирования команд 16 битной схемы и 32 битной. Но это легко решается используя управляющие слова "use16" и "use32" подробнее зависит от компилятора.

    Вторая проблема это смещения. Надо чтобы компилятор и правильно выставил или твой инсталятор. Это нетрудно.
     
  4. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    Компилятор - masm32, который, кажется, 16-битный код уже не поддерживает.
    Хм. Понятно, спасибо. Тут нарисовалась другая проблема - вышеуказанный код я собрал фасмом и записал в MBR, сохранив старую в нужный сектор. VirtualBox при запуске выдало примерно следующее: "int13_harddisk: function 42. Can't use 64bits lba", и это притом, что я читаю в CHS, а функция 02, а не 42. Я подозреваю, что я где-то натупил со смещениями на этапе переноса тела загрузчика в другую область памяти, и он прыгнул не в то место. В какую сторону нужно копать?
     
  5. l_inc

    l_inc New Member

    Blog Posts:
    0
    Joined:
    Sep 29, 2005
    Messages:
    2,566
    drunken_cowboy
    Code (Text):
    1. mov    si, (payload + 7C00h)
    Здесь неверно, т.к. согласно вышестоящему org 7C00h отсчёт адресов всех меток, включая payload, уже идёт начиная с базы 7C00h.
     
  6. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    Чёёрт, точно, прошляпил. После редактирования:
    Code (Text):
    1.     use16
    2.     org 7C00h                              
    3.                         ; Загрузим себя по другому адресу
    4.                         ; Но не весь код, а только с
    5.                         ; метки payload
    6.  
    7.     xor ax,ax
    8.     mov ds,ax
    9.     mov es,ax
    10.     mov ss,ax
    11.     mov sp,7B00h           
    12.  
    13.     cld
    14.     mov si, payload
    15.     mov di, 7D00h
    16.     mov cx, 200h
    17.     rep movsb                      
    18.  
    19.     jmp 0000:7D00h          ; far jump на копию нашего кода
    20. payload:
    21. ...
    При загрузке это дело намертво зависает, а толкового мана по отладке загрузчиков я так и не нашёл. Вообще, вот такой трюк сработал:

    Code (Text):
    1. org 0600h
    2. use16
    3. xor ax,ax
    4. mov ds,ax
    5. mov es,ax
    6. mov ss,ax
    7. mov sp,7C00h
    8.  
    9. cld
    10. mov si, 7C00h
    11. mov di, 600h
    12. mov cx, 200h
    13. rep movsb  
    14. jmp 0000:payload
    15.  
    16. payload:    
    17. ...
    Вроде схема примерно одинаковая, где тут может быть загвоздка? Обидно, что ошибся в десяти строчках, а не знаю, где. Вроде и
     
  7. acckiitvar

    acckiitvar Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    71
    Могу предложить поотлаживаться на SimNow. Там есть встроенный отладник.
     
  8. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    У меня 32-битная система, увы.
     
  9. Phantom_84

    Phantom_84 New Member

    Blog Posts:
    0
    Joined:
    Jun 6, 2007
    Messages:
    820
    Я думал, мы не обсуждаем код... Твои 7B00h, 7D00h меня пугают. Действительно на ровном месте столько неоднозначных вещей понаделал... Если чЁ, то вершину стека можно устанавливать на 7С00h, а 7C00h+512 = 7E00h. Твое желание перемещать только полезный код похвально, но если это делать необдуманно, то опять можно наломать дров со смещениями. fasm в отличие от нек. др. компиляторов позволяет делать такие вещи достаточно элегантно. Вот немного обобщенный вариант разметки, используемый в моих MBR-загрузчиках.
    Code (Text):
    1.         org 7C00h
    2. start:
    3.         xor cx,cx
    4.         cli
    5.         mov ss,cx
    6.         mov sp,$$
    7.         sti
    8.         mov ds,cx
    9.         mov si,old_base - old_base mod 2
    10.         mov es,cx
    11.         mov di,new_base - old_base mod 2
    12.         cld
    13.         mov cl,(size+1)/2
    14.         rep movsw
    15.  
    16.         jmp 0:new_base
    17.  
    18.         rb 440-($-$$)-size
    19. old_base:
    20.         org 600h ; 7E00h
    21. new_base:
    22.         ...
    23. ; необязательно, просто четный размер гарантирует
    24. ; выравнивание перемещаемого кода на четную границу,
    25. ; что улучшит эффективность при перемещении словами
    26.         align 2
    27.         label size at $-$$
    Это не самая простая разметка. Можно проще:
    Code (Text):
    1.   org 7C00h
    2.   ...
    3.   align 2
    4. old_base:
    5.   org 600h
    6. new_base:
    7.   ...
    8.   org old_base+($-$$) ; old_base+size
    9.   db 7C00h+440-$ dup 0
     
  10. Phantom_84

    Phantom_84 New Member

    Blog Posts:
    0
    Joined:
    Jun 6, 2007
    Messages:
    820
    Да, забыл сказать, что сложность первой разметки вызвана тем, что я перемещаемый код обычно размещаю под верхней границей доступной области MBR.
     
  11. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    Однако да. Читая сектор по адресу 7C00h, я затирал скопированный код, поэтому там и творилось нечто невообразимое. Спасибо. Приму к сведению, в т.ч. и код.
     
  12. drunken_cowboy

    drunken_cowboy New Member

    Blog Posts:
    0
    Joined:
    Sep 26, 2011
    Messages:
    6
    Ещё такой вопрос, могу ли я использовать 32-битный код в MBR?
     
  13. FatMoon

    FatMoon New Member

    Blog Posts:
    0
    Joined:
    Nov 28, 2002
    Messages:
    954
    Location:
    Russia
    drunken_cowboy
    запретов-то нет... хоть 64-битный. Только тогда там же надо размещать загрузку чего-то еще, и переход в PM, и минимальные драйвера для продолжения работы с диском, и ... Где-то поблизости и недавно была тема похожая, с мудрым советом "не надо впихивать невпихуемое". Пусть МБР делает свою часть - читает в память некий лоадер и передает ему управление. Лоадер может быть бОльшего размера, не ограничен в 1-2 сектора. Впихнуть в МБР инициализацию защищенного режима, драйвер диска, обработчики аппаратных прерываний и исключений - не буду говорить "невозможно", хз, Левши имеются, и блоху подкуют. Но не нужно - и сложно - и при этом чем-то придется пожертвовать (например, проверками на успех дисковых операций, или совместимостью с железом).
     
  14. Phantom_84

    Phantom_84 New Member

    Blog Posts:
    0
    Joined:
    Jun 6, 2007
    Messages:
    820
    "32-разрядные инструкции" можешь, но компилируй под use16.
     
  15. Novishok

    Novishok New Member

    Blog Posts:
    0
    Joined:
    Mar 18, 2012
    Messages:
    5
    [modnote=TermoSINteZ]Вам предупреждение , за дублирование сообщения в разных ветках форума[/modnote]