помогите разобраться с загрузчиком

Тема в разделе "WASM.BEGINNERS", создана пользователем pashe4ka13, 23 окт 2010.

  1. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Здравствуйте уважаемые форумчане!!! Вот код загрузчика написанного на NASM:
    Код (Text):
    1.  org 0x7C00
    2.  jmp     BootStart
    3.  nop
    4.  BS_OEMName     db 'FLESHKA+'
    5.  BPB_BytsPerSec dw 0x200
    6.  BPB_SecPerClus db 1
    7.  BPB_RsvdSecCnt dw 1
    8.  BPB_NumFATs    db 2
    9.  BPB_RootEntCnt dw 224
    10.  BPB_TotSec16   dw 2880
    11.  BPB_Media      db 0xF0
    12.  BPB_FATsz16    dw 9
    13.  BPB_SecPerTrk  dw 18
    14.  BPB_NumHeads   dw 2
    15.  BPB_HiddSec    dd 0
    16.  BPB_TotSec32   dd 0
    17.  BS_DrvNum      db 0
    18.  BS_ResNT       db 0
    19.  BS_BootSig     db 29h
    20.  BS_VolID       dd 77777777h
    21.  BS_VolLab      db 'X boot disk'
    22.  BS_FilSysType  db 'FAT12   '
    23.  ; Структура элемента каталога
    24.  struc  DirItem
    25.         DIR_Name:       resb 11
    26.         DIR_Attr:       resb 1
    27.         DIR_ResNT:      resb 1
    28.         DIR_CrtTimeTenth        resb 1
    29.         DIR_CrtTime:    resw 1
    30.         DIR_CrtDate:    resw 1
    31.         DIR_LstAccDate: resw 1
    32.         DIR_FstClusHi:  resw 1
    33.         DIR_WrtTime:    resw 1
    34.         DIR_WrtDate:    resw 1
    35.         DIR_FstClusLow: resw 1
    36.         DIR_FileSize:   resd 1
    37.  endstruc ;DirItem
    38.  
    39.  
    40. ; Наши не инициализированные переменные
    41.  ; При инициализации они затрут не нужные нам
    42.  ; поля заголовка FAT: BS_jmpBoot и BS_OEMName
    43.  struc  NotInitData
    44.         SysSize:        resd 1  ; Размер системной области FAT
    45.         fails:  resd 1  ; Число неудачных попыток при чтении
    46.         fat:    resd 1  ; Номер загруженного сектора с элементами FAT
    47.  endstruc ;NotInitData
    48.  ; По этому адресу мы будем загружать загрузчик
    49.  %define SETUP_ADDR     0x1000
    50.  ; А по этому адресу нас должны были загрузить
    51.  %define BOOT_ADDR      0x7C00
    52.  %define BUF    0x500
    53.  BootStart:
    54.         cld
    55.         xor     cx, cx
    56.         mov     ss, cx
    57.         mov     es, cx
    58.         mov     ds, cx
    59.         mov     sp, BOOT_ADDR
    60.         mov     bp, sp
    61.         ; Сообщим о том что мы загружаемся
    62.         mov     si, BOOT_ADDR + mLoading
    63.         call    print
    64.  
    65.         mov     al, [byte bp+BPB_NumFATs]
    66.         cbw
    67.         mul     word [byte bp+BPB_FATsz16]
    68.         add     ax, [byte bp+BPB_HiddSec]
    69.         adc     dx, [byte bp+BPB_HiddSec+2]
    70.         add     ax, [byte bp+BPB_RsvdSecCnt]
    71.         adc     dx, cx
    72.         mov     si, [byte bp+BPB_RootEntCnt]
    73.         ; dx:ax - Номер первого сектора корневого каталога
    74.         ; si - Количество элементов в корневом каталоге
    75.         pusha
    76.         ; Вычислим размер системной области FAT = резервные сектора +
    77.         ; все копии FAT + корневой каталог
    78.         mov     [bp+SysSize], ax        ; осталось добавить размер каталога
    79.         mov     [bp+SysSize+2], dx
    80.         ; Вычислим размер корневого каталога
    81.         mov     ax, 32
    82.         mul     si
    83.         ; dx:ax - размер корневого каталога в байтах, а надо в секторах
    84.         mov     bx, [byte bp+BPB_BytsPerSec]
    85.         add     ax, bx
    86.         dec     ax
    87.         div     bx
    88.         ; ax - размер корневого каталога в секторах
    89.         add     [bp+SysSize], ax        ; Теперь мы знаем размер системной
    90.         adc     [bp+SysSize+2], cx      ; области FAT, и начало области данных
    91.         popa
    92.         ; В dx:ax - снова номер первого сектора корневого каталога
    93.         ; si - количество элементов в корневом каталоге
    94.  
    95.  
    96.  
    97. NextDirSector:
    98.         ; Загрузим очередной сектор каталога во временный буфер
    99.         mov     bx, 700h        ; es:bx - буфер для считываемого сектора
    100.         mov     di, bx  ; указатель текущего элемента каталога
    101.         mov     cx, 1   ; количество секторов для чтения
    102.         call    ReadSectors
    103.         jc      near DiskError  ; ошибка при чтении
    104.  RootDirLoop:
    105.         ; Ищем наш файл
    106.         ; cx = 0 после функции ReadSectors
    107.         cmp     [di], ch        ; byte ptr [di] = 0?
    108.         jz      near NotFound   ; Да, это последний элемент в каталоге
    109.         ; Нет, не последний, сравним имя файла
    110.         pusha
    111.         mov     cl, 11  ; длина имени файла с расширением
    112.         mov     si, BOOT_ADDR + LoaderName      ; указатель на имя искомого файла
    113.         rep     cmpsb   ; сравниваем
    114.         popa
    115.         jz      short Found     ; Нашли, выходим из цикла
    116.         ; Нет, ищем дальше
    117.         dec     si      ; RootEntCnt
    118.         jz      near NotFound   ; Это был последний элемент каталога
    119.         add     di, 32  ; Переходим к следующему элементу каталога
    120.         ; bx указывает на конец прочтенного сектора после call ReadSectors
    121.         cmp     di, bx  ; Последний элемент в буфере?
    122.         jb      short RootDirLoop       ; Нет, проверим следующий элемент
    123.         jmp     short NextDirSector     ; Да последний, загрузим следующий сектор
    124.  
    125. Found:
    126.         ; Загрузка загрузчика (извените, калабур)
    127.         mov     bx, SETUP_ADDR
    128.         mov     ax, [byte di+DIR_FstClusLow]    ; Номер первого кластера файла
    129.         ; Загружаем сектор с элемнтами FAT, среди которых есть FAT[ax]
    130.         ; LoadFAT сохраняет значения всех регистров
    131.         call    LoadFAT
    132.  ReadCluster:
    133.         ; ax - Номер очередного кластера
    134.         ; Загрузим его в память
    135.         push    ax
    136.         ; Первые два элемента FAT служебные
    137.         dec     ax
    138.         dec     ax
    139.         ; Число секторов для чтения
    140.         ; cx = 0 после ReadSectors
    141.         mov     cl, [byte bp+BPB_SecPerClus]    ; Секторов на кластер
    142.         mul     cx
    143.         ; dx:ax - Смещение кластера относительно области данных
    144.         add     ax, [byte bp+SysSize]
    145.         adc     dx, [byte bp+SysSize+2]
    146.         ; dx:ax - Номер первого сектора требуемого кластера
    147.         ; cx еще хранит количество секторов на кластер
    148.         ; es:bx - конец прошлого кластера и начало нового
    149.         call    ReadSectors     ; читаем кластер
    150.         jc      near DiskError  ; Увы, ошибка чтения
    151.         pop     ax      ; Номер кластера
    152.         ; Это конец файла?
    153.         ; Получим значение следующего элемента FAT
    154.         pusha
    155.         ; Вычислим адрес элемента FAT
    156.         mov     bx, ax
    157.         shl     ax, 1
    158.         add     ax, bx
    159.         shr     ax, 1
    160.         ; Получим номер сектора, в котором находится текущий элемент FAT
    161.         cwd
    162.         div     word [byte bp+BPB_BytsPerSec]
    163.         cmp     ax, [bp+fat]    ; Мы уже читали этот сектор?
    164.         popa
    165.         je      Checked ; Да, читали
    166.         ; Нет, надо загрузить этот сектор
    167.         call    LoadFAT
    168.  Checked:
    169.         ; Вычислим адрес элемента FAT в буфере
    170.         push    bx
    171.         mov     bx, ax
    172.         shl     bx, 1
    173.         add     bx, ax
    174.         shr     bx, 1
    175.         and     bx, 511 ; остаток от деления на 512
    176.         mov     bx, [bx+0x700]  ; а вот и адрес
    177.         ; Извлечем следующий элемент FAT
    178.         ; В FAT16 и FAT32 все немного проще :(
    179.         test    al, 1
    180.         jnz     odd
    181.         and     bx, 0xFFF
    182.         jmp     short done
    183.  odd:
    184.         shr     bx, 4
    185.  done:
    186.         mov     ax, bx
    187.         pop     bx
    188.         ; bx - новый элемент FAT
    189.         cmp     ax, 0xFF8       ; EOF - конец файла?
    190.         jb      ReadCluster     ; Нет, читаем следующий кластер
    191.         ; Наконец-то загрузили
    192.         mov     ax, SETUP_ADDR>>4       ; SETUP_SEG
    193.         mov     es, ax
    194.         mov     ds, ax
    195.         ; Передаем управление, наше дело сделано :)
    196.         jmp     SETUP_ADDR>>4:0
    197.        
    198.  LoadFAT        ;proc
    199.  ; Процедура для загрузки сектора с элементами FAT
    200.  ; Элемент ax должен находится в этом секторе
    201.  ; Процедура не должна менять никаких регистров
    202.         pusha
    203.         ; Вычисляем адрес слова содержащего нужный элемент
    204.         mov     bx, ax
    205.         shl     ax, 1
    206.         add     ax, bx
    207.         shr     ax, 1
    208.         cwd
    209.         div     word [byte bp+BPB_BytsPerSec]
    210.         ; ax - смещение сектора относительно начала таблицы FAT
    211.         mov     [bp+fat], ax    ; Запомним это смещение, dx = 0
    212.         cwd                     ; dx:ax - номер сектора, содержащего FAT[?]
    213.         ; Добавим смещение к первой копии таблицы FAT
    214.         add     ax, [byte bp+BPB_RsvdSecCnt]
    215.         adc     dx, 0
    216.         add     ax, [byte bp+BPB_HiddSec]
    217.         adc     dx, [byte bp+BPB_HiddSec+2]
    218.         mov     cx, 1   ; Читаем один сектор. Можно было бы и больше, но не быстрее
    219.         mov     bx, 700h        ; Адрес буфера
    220.         call    ReadSectors
    221.         jc      DiskError       ; Ошибочка вышла
    222.         popa
    223.         ret
    224.  ;LoadFAT       endp
    225.   ; *          Чтение секторов с диска              *
    226.  ; *************************************************
    227.  ; * Входные параметры:                            *
    228.  ; * dx:ax       - (LBA) номер сектора             *
    229.  ; * cx          - количество секторов для чтения  *
    230.  ; * es:bx       - адрес буфера                    *
    231.  ; *************************************************
    232.  ; * Выходные параметры:                           *
    233.  ; * cx       - Количество не прочтенных секторов  *
    234.  ; * es:bx    - Указывает на конец буфера          *
    235.  ; * cf = 1   - Произошла ошибка при чтении        *
    236.  ; *************************************************
    237.  ReadSectors    ;proc
    238.  next_sector:
    239.         ; Читаем очередной сектор
    240.         mov     byte [bp+fails], 3      ; Количество попыток прочесть сектор
    241.  try:
    242.         ; Очередная попытка
    243.         pusha
    244.         ; Преобразуем линейный адрес в CSH
    245.         ; dx:ax = a1:a0
    246.         xchg    ax, cx          ; cx = a0
    247.         mov     ax, [byte bp+BPB_SecPerTrk]
    248.         xchg    ax, si          ; si = Scnt
    249.         xchg    ax, dx          ; ax = a1
    250.         xor     dx, dx
    251.         ; dx:ax = 0:a1
    252.         div     si              ; ax = q1, dx = c1
    253.         xchg    ax, cx          ; cx = q1, ax = a0
    254.         ; dx:ax = c1:a0
    255.         div     si              ; ax = q2, dx = c2 = c
    256.         inc     dx              ; dx = Sector?
    257.         xchg    cx, dx          ; cx = c, dx = q1
    258.         ; dx:ax = q1:q2
    259.         div     word [byte bp+BPB_NumHeads]     ; ax = C (track), dx = H
    260.         mov     dh, dl          ; dh = H
    261.         mov     ch, al
    262.         ror     ah, 2
    263.         or      cl, ah
    264.         mov     ax, 0201h               ; ah=2 - номер функции, al = 1 сектор
    265.         mov     dl, [byte bp+BS_DrvNum]
    266.         int     13h
    267.         popa
    268.         jc      Failure ; Ошибка при чтении
    269.         ; Номер следующего сектора
    270.         inc     ax
    271.         jnz     next
    272.         inc     dx
    273.  next:
    274.         add     bx, [byte bp+BPB_BytsPerSec]
    275.         dec     cx      ; Все сектора прочтены?
    276.         jnz     next_sector     ; Нет, читаем дальше
    277.  return:
    278.         ret
    279.  Failure:
    280.         dec     byte [bp+fails] ; Последняя попытка?
    281.         jnz     try     ; Нет, еще раз
    282.         ; Последняя, выходим с ошибкой
    283.         stc
    284.         ret
    285.  
    286.  ;ReadSectors   endp
    287.  
    288.  
    289.  
    290. ; Сообщения об ошибках
    291.  NotFound:      ; Файл не найден
    292.         mov     si, BOOT_ADDR + mLoaderNotFound
    293.         call    print
    294.         jmp     short die
    295.  DiskError:     ; Ошибка чтения
    296.         mov     si, BOOT_ADDR + mDiskError
    297.         call    print
    298.         ;jmp    short die      
    299.  die:   ; Просто ошибка
    300.         mov     si, BOOT_ADDR + mReboot
    301.         call    print
    302.  _die:  ; Бесконечный цикл, пользователь сам нажмет Reset
    303.         jmp     short _die
    304.  ; Процедура вывода ASCIIZ строки на экран
    305.  ; ds:si - адрес строки
    306.  print: ; proc
    307.         pusha
    308.  print_char:
    309.         lodsb   ; Читаем очередной символ
    310.         test    al, al  ; 0 - конец?
    311.         jz      short pr_exit   ; Да конец
    312.         ; Нет, выводим этот символ
    313.         mov     ah, 0eh
    314.         mov     bl, 7
    315.         int     10h
    316.         jmp     short print_char        ; Следующий
    317.  pr_exit:
    318.         popa
    319.         ret
    320.  ;print endp
    321.  ; Перевод строки
    322.  %define        endl 10,13,0
    323.  ; Строковые сообщения
    324.  mLoading       db 'Loading...',endl
    325.  mDiskError     db 'Disk I/O error',endl
    326.  mLoaderNotFound        db 'Loader not found',endl
    327.  mReboot                db 'Reboot system',endl
    328.  ; Выравнивание размера образа на 512 байт
    329.  times 499-($-$$) db 0
    330.  LoaderName     db 'BOOTOR     '        ; Имя файла загрузчика
    331.  BootMagic      dw 0xAA55       ; Сигнатура загрузочного сектора
    Заливаю его на флешку, начинаю загрузку с неё, получаю сообшение Loading...
    Loader not found
    Reboot system

    Почему он не находит мой фаил? Может ли это быть связано с тем, что флешка перед заливкой не была отформатирована?
     
  2. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Вот еще беда :dntknw: Неформатируется ;(
    format I: /FS:FAT12 /A:512
    Вставьте новый диск в дисковод I:
    и нажмите клавишу ENTER...
    Тип файловой системы: RAW.
    Новая файловая система: FAT12.
    FORMAT недопустим для дисков FAT12.
     
  3. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    А не format'ом? Сторонней утилитой. или даже самому забить нулями, а потом форматнуть.
     
  4. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Например какой утилитой? Что то те которые я нашел в FAT12 не форматируют
     
  5. SII

    SII Воин против дзена

    Публикаций:
    0
    Регистрация:
    31 окт 2007
    Сообщения:
    1.483
    Адрес:
    Подмосковье
    А зачем ФАТ12? Делайте уже сразу ФАТ32 -- это не шибко сложней, а кой в чём даже проще.
     
  6. Lietarius

    Lietarius New Member

    Публикаций:
    0
    Регистрация:
    15 май 2011
    Сообщения:
    1
    какой знакомый загрузчик....

    во первых форматни флеху как фат16 и поменяй кусок кода

    mov bx, ax
    shl bx, 1
    add bx, ax
    shr bx, 1

    (в нескольких местах) на такой

    mov bx, ax
    mul bx,2

    для фат 32
    mov bx, ax
    mul bx,4
     
  7. Igor1024

    Igor1024 Васил Троянов Боянов (Azis)

    Публикаций:
    0
    Регистрация:
    15 окт 2010
    Сообщения:
    345
    Адрес:
    Sliven, Bulgaria
    pashe4ka13, bootloader от Колибри тож можно разобрать. Там всё прокоментировано и понятно. Он, правда, под FAT12, но на FAT32 переписать недолго.
     
  8. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Спасибо огромное всем за ответы, данную проблему я давно решил написав загрузчик самостоятельно на фасме, тему можно закрыть.