Организация большого проекта под DOS на fasm

Тема в разделе "WASM.BEGINNERS", создана пользователем aus, 15 янв 2008.

  1. aus

    aus New Member

    Публикаций:
    0
    Регистрация:
    27 сен 2006
    Сообщения:
    13
    Набив руку на небольших программах на ассемблере, решил взяться за более серьезную задачу. И как следствие встала задача наиболее рационально оргинизовать процесс написания. Интересуют мнения об следующих вопросах
    1. разбиения программы на модули ( модуль вывода на экран, модуль работы с файлами).
    2. вызов процедур, передача параметров, возвращения результата из функции.
    3. объявление локальных и глобальных переменных, структур, массивов.

    Как наиболее оптимально спроектировать каркас программы? Кто какого приципа придерживается? На какие подводные камни можно наступить?
     
  2. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    aus
    К фасму идет небольшая демка в исходниках kelvar.zip. Можно посмотреть как там составлен проект. Ну и исходники самого fasm'a тоже поглядеть ;).
     
  3. aus

    aus New Member

    Публикаций:
    0
    Регистрация:
    27 сен 2006
    Сообщения:
    13
    Спасибо, censored. То что нужно, однако тему не закрываю.
    Есть еще такие же проекты под DOS? Где можно посмотреть?
     
  4. Vov4ick

    Vov4ick Владимир

    Публикаций:
    0
    Регистрация:
    8 окт 2006
    Сообщения:
    581
    Адрес:
    МО
    В примерах к TASM'у есть большая программка FILT и другие. Но то TASM и FASM вроде не дошёл до его уровня при организации многомодульных проектов.
     
  5. aus

    aus New Member

    Публикаций:
    0
    Регистрация:
    27 сен 2006
    Сообщения:
    13
    Как в фасме обстоит дело с повторным использованием уже написанного кода? Есть ли возможность написать библиотеку для работы с экраном и в дальнейшем подключать ее к другим проектам? Если нет, то кто как выкручивается из данной ситуации?
     
  6. Vov4ick

    Vov4ick Владимир

    Публикаций:
    0
    Регистрация:
    8 окт 2006
    Сообщения:
    581
    Адрес:
    МО
    Директива include есть, значит можно. :derisive:
     
  7. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Модуль может быть представлен двумя файлами:

    Module.Inc - здесь описана структура объекта с которым работает данный модуль. Например:
    Код (Text):
    1. virtual at 0
    2. Module:
    3.     .Member1 dw ?
    4.     .Member2 dw ?
    5.     .Member3 dw ?
    6.     .Member4 dw ?
    7.     .size = $
    8. end virtual
    Module.Asm - здесь лежат собственно функции работы с той структурой, которая описана в Module.Inc. Имя функции составлено из частей: имя модуля + имя собственно функции. Между ними можно поставить знак подчёркивания (или не надо... по-вкусу). Таким образом если есть две функции с именем Show для двух модулей, то их имена: Module1_Show и Module2_Show. Легче читать большой код с таким подходом:
    Код (Text):
    1. ;
    2. ; Labels inside functions should begin with a dot - this way there will
    3. ; be no duplicate labels in all of the modules.
    4. ;
    5. Module_Init:
    6.     ; TODO: write code here ...
    7.  
    8. .done:
    9.     ret
    10.  
    11. Module_Cleanup:
    12.     ; TODO: write code here ...
    13.  
    14. .done:
    15.     ret
    Затем эти два файла, естественно, включены в основной файл, там где описаны все секции:
    Код (Text):
    1. ; MS-DOS COM File Template
    2.  
    3.     org     100h                   ; COM File Format
    4.     use16                          ; Use 16-bit opcodes
    5.  
    6. ; Definitions
    7.  
    8.     include 'Module1.Inc'
    9.     include 'Module2.Inc'
    10.     ;{INCLDEF} (Definitions will be inserted before this line)
    11.  
    12.     PROC_ALIGN equ 4
    13.  
    14. ; Entry Point
    15.  
    16.     mov     dx, strHello           ; Print to console
    17.     mov     ah, 9
    18.     int     21h
    19.  
    20.     int     20h                    ; Quit to MS-DOS
    21.  
    22. ; Code Modules
    23.  
    24.     include 'Module1.Asm'
    25.     include 'Module2.Asm'
    26.     ;{INCLIMPL} (Code modules will be inserted before this line)
    27.  
    28. ; Data Section
    29.  
    30.     include 'Module1.Glb'
    31.     include 'Module2.Glb'
    32.     ;{INCLDATA} (Data modules will be inserted before this line)
    33.  
    34. strHello    db 'Hello, World!$'
    Иногда бывает ситуация, где модулю надо использовать глобальные переменные. Тогда неплохо иметь ещё один включаемый файл (например Module.Glb), где эти переменные объявлены. Тогда модуль можно легко перенести из одной программы в другую.

    Передача параметров? Можно в регистрах, а можно в стеке. FASM имеет макро-команды для таких функций. Лично мне нравится передавать параметры в регистрах - всё таки это Ассемблер а не Си.

    Локальные переменные можно сделать двумя основными способами:

    1. Адресация через регистр BP (или EBP):
    http://en.wikibooks.org/wiki/Reverse_Engineering/Functions_and_Stack_Frames
    (Также можно использовать инструкции процессора ENTER и LEAVE, но они чуть медленнее чем прямые манипуляции с регистрами SP/BP.)

    2. Адресация через регистр SP (или ESP):
    Код (Text):
    1. virtual at 0
    2. loc1:
    3.     .locvar1 dw ?
    4.     .locvar2 dw ?
    5.     .locvar3 dw ?
    6.     .size = $
    7. end virtual
    8.  
    9. Module_FuncWithLocals:
    10.     sub sp, loc1.size     ; reserve room for locals
    11.  
    12.     ; using local variables
    13.     mov [sp + loc1.locvar1], ax
    14.     mov cx, [sp + loc1.locvar2]
    15.  
    16.     ; loading address of local variable
    17.     lea di, [sp + loc1.locvar3]
    18.  
    19.  
    20.  
    21.  
    22.  
    23. .exit:
    24.     add sp, loc1.size     ; release room for locals
    25.     ret
    Размер локальных переменных должен быть выровнен на границу слова (2 байта). Так, что если нужен один байт как локальная переменная - используется резервное место для выравнивания:
    Код (Text):
    1. virtual at 0
    2. loc2:
    3.     .locvar1 dw ?
    4.     .locvar2_byte db ?
    5.     .reserved1 db ?
    6.     .locvar3 dw ?
    7.     .size = $
    8. end virtual