Набив руку на небольших программах на ассемблере, решил взяться за более серьезную задачу. И как следствие встала задача наиболее рационально оргинизовать процесс написания. Интересуют мнения об следующих вопросах 1. разбиения программы на модули ( модуль вывода на экран, модуль работы с файлами). 2. вызов процедур, передача параметров, возвращения результата из функции. 3. объявление локальных и глобальных переменных, структур, массивов. Как наиболее оптимально спроектировать каркас программы? Кто какого приципа придерживается? На какие подводные камни можно наступить?
aus К фасму идет небольшая демка в исходниках kelvar.zip. Можно посмотреть как там составлен проект. Ну и исходники самого fasm'a тоже поглядеть .
Спасибо, censored. То что нужно, однако тему не закрываю. Есть еще такие же проекты под DOS? Где можно посмотреть?
В примерах к TASM'у есть большая программка FILT и другие. Но то TASM и FASM вроде не дошёл до его уровня при организации многомодульных проектов.
Как в фасме обстоит дело с повторным использованием уже написанного кода? Есть ли возможность написать библиотеку для работы с экраном и в дальнейшем подключать ее к другим проектам? Если нет, то кто как выкручивается из данной ситуации?
Модуль может быть представлен двумя файлами: Module.Inc - здесь описана структура объекта с которым работает данный модуль. Например: Код (Text): virtual at 0 Module: .Member1 dw ? .Member2 dw ? .Member3 dw ? .Member4 dw ? .size = $ end virtual Module.Asm - здесь лежат собственно функции работы с той структурой, которая описана в Module.Inc. Имя функции составлено из частей: имя модуля + имя собственно функции. Между ними можно поставить знак подчёркивания (или не надо... по-вкусу). Таким образом если есть две функции с именем Show для двух модулей, то их имена: Module1_Show и Module2_Show. Легче читать большой код с таким подходом: Код (Text): ; ; Labels inside functions should begin with a dot - this way there will ; be no duplicate labels in all of the modules. ; Module_Init: ; TODO: write code here ... .done: ret Module_Cleanup: ; TODO: write code here ... .done: ret Затем эти два файла, естественно, включены в основной файл, там где описаны все секции: Код (Text): ; MS-DOS COM File Template org 100h ; COM File Format use16 ; Use 16-bit opcodes ; Definitions include 'Module1.Inc' include 'Module2.Inc' ;{INCLDEF} (Definitions will be inserted before this line) PROC_ALIGN equ 4 ; Entry Point mov dx, strHello ; Print to console mov ah, 9 int 21h int 20h ; Quit to MS-DOS ; Code Modules include 'Module1.Asm' include 'Module2.Asm' ;{INCLIMPL} (Code modules will be inserted before this line) ; Data Section include 'Module1.Glb' include 'Module2.Glb' ;{INCLDATA} (Data modules will be inserted before this line) 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): virtual at 0 loc1: .locvar1 dw ? .locvar2 dw ? .locvar3 dw ? .size = $ end virtual Module_FuncWithLocals: sub sp, loc1.size ; reserve room for locals ; using local variables mov [sp + loc1.locvar1], ax mov cx, [sp + loc1.locvar2] ; loading address of local variable lea di, [sp + loc1.locvar3] .exit: add sp, loc1.size ; release room for locals ret Размер локальных переменных должен быть выровнен на границу слова (2 байта). Так, что если нужен один байт как локальная переменная - используется резервное место для выравнивания: Код (Text): virtual at 0 loc2: .locvar1 dw ? .locvar2_byte db ? .reserved1 db ? .locvar3 dw ? .size = $ end virtual