Создание системы стандартных макросов для FASM

Тема в разделе "WASM.PROJECTS", создана пользователем Miller Rabin, 20 июл 2008.

  1. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    Почитал тут последние посты и решил начать данный проект.

    Умелое использование макросов позволяет скрывать рутинную последовательность действий за
    вполне понятным именем, отражающим его суть.
    Макросы, созданию и описанию которых я хотел бы посветить немного времени, будут придерживаться
    концепции "Скрывать второстепенное".

    Для начала я хотел бы представить технологию создания макросов, которой пользуюсь я.
    И если она найдет отклик в ваших сердцах, то вы могли бы помочь в ее улучшении и доступности, чтобы
    в дальнейшем использовать ее как основу для построения макросов, которые бы не запутывали,
    а наоборот повышали читабельность и гибкость программ, написанных на ассемблере.

    Структура сильно напоминает ООП
    Макрос может содержать поля и методы для работы с полями. И носит гордое имя - Объект! Хех!
    И все же это не ООП - это всего лишь набор макросов.

    Первым делом необходима какая-то база, от которой можно отталкиваться при построении макроса.
    Код (Text):
    1. ;Базовый объект, от него удобно наследовать другие объекты
    2. macro TObject name
    3. {
    4.  
    5. ;Метод сохраняет поля объекта в том месте где данный объект будет вызван
    6. macro name#.Store
    7. \{
    8.     name#.StartInstance:
    9.     match =TRUE, name#.Virtual
    10.     \\{
    11.         purge name#.SetPointer
    12.         macro name#.SetPointer \\\{     \\\}
    13.     \\}
    14.     name#.SetPointer
    15. \}
    16.  
    17. ;Метод устанавливает указатель на объект. Используется только в методе Store
    18. macro name#.SetPointer
    19. \{
    20.     name:
    21. \}
    22.  
    23. ;Метод позволяет адресовать объект относительно регистра или массива данных
    24. macro name#.At AddressSpace
    25. \{
    26. name EQU AddressSpace
    27. name#.Virtual EQU TRUE
    28. virtual at AddressSpace
    29.     ..InVirtual = 1
    30.     name#.Store
    31.     ..InVirtual = 0
    32. end virtual
    33. \}
    34.  
    35. ;Метод затирает все поля объекта нулями
    36. macro name#.Cleanup
    37. \{
    38.   push edi
    39.   argmov edi, name
    40.   xor     eax, eax
    41.   mov     ecx, name#.Size/4
    42.   rep stosd
    43.   pop edi
    44. \}
    45.  
    46. ;Метод устанавливает размер объекта
    47. macro name#.SetSize
    48. \{
    49.    name#.Size = $ - name#.StartInstance
    50. \}
    51.  
    52. }
    Что делает данный объект? Да ничего он не деляет просто дает наследуемым от него объектам
    ряд интересных свойств.
     
  2. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    Использование объекта TObject для создания полезных макросов
    Код (Text):
    1. macro TFile name
    2. {
    3.  
    4. TObject name            ;Здесь осуществляется наследование
    5.  
    6. macro name#.Store               ;Переопределяем метод Store
    7. \{
    8.     name#.Store                     ;Вызывем метод Store от родительского объекта
    9.     name#.Handle    DD  0       ;Объявляем поле Handle
    10.     name#.SetSize                   ;Устанавливаем размер нашего нового объекта
    11. \}
    12.  
    13.  
    14. ;Думаю назначение этих методов понятно и без комментариев
    15. ;Звездочками помечены параметры, который нужно обязятельно указывать.
    16. ;параметры без звездочек можно не писать. Они будут заменены значениями по умолчанию
    17.  
    18. macro name#.Write Buffer*, Length*, Bytes, Overlapped
    19. \{
    20.     if Overlapped eq
    21.         push 0
    22.     else
    23.         push Overlapped
    24.     end if
    25.     if Bytes eq
    26.         pushd esp
    27.     else
    28.         pushd Tag  
    29.     end if
    30.     pushd Length
    31.     pushd Buffer
    32.     pushd [name#.Handle]
    33.     call [WriteFile]
    34. \}
    35.  
    36. macro name#.Read Buffer*, Length*, Bytes, Overlapped
    37. \{
    38.     if Overlapped eq
    39.         push 0
    40.     else
    41.         push Overlapped
    42.     end if
    43.     if Bytes eq
    44.         pushd esp
    45.     else
    46.         pushd Bytes
    47.     end if
    48.     pushd Length
    49.     pushd Buffer
    50.     pushd [name#.Handle]
    51.     call [ReadFile]
    52. \}
    53.  
    54. macro name#.CreateFile Path*, Access, Creation, Share, Security, Flags, Template
    55. \{
    56.     if Template eq
    57.         push 0
    58.         else
    59.         pushd Template
    60.     end if
    61.  
    62.     if Flags eq
    63.         push FILE_ATTRIBUTE_NORMAL
    64.     else
    65.         pushd Flags
    66.     end if
    67.  
    68.     if Creation eq
    69.         push OPEN_EXISTING
    70.     else
    71.         pushd Creation
    72.     end if
    73.  
    74.     if Security eq
    75.         push 0
    76.     else   
    77.         pushd Security
    78.     end if
    79.  
    80.     if Share eq
    81.         push FILE_SHARE_READ
    82.     else
    83.         pushd Share
    84.     end if
    85.  
    86.     if Access eq
    87.         push GENERIC_READ
    88.         else
    89.         pushd Access
    90.     end if
    91.  
    92.     pushd Path
    93.     call [CreateFile]  
    94.     mov [name#.Handle], eax
    95. \}
    96.  
    97. macro name#.Close
    98. \{
    99.     invoke CloseHandle, [name#.Handle]
    100. \}
    101.  
    102. macro name#.GetPosition
    103. \{
    104.     invoke SetFilePointer, [name#.Handle], 0,0, FILE_CURRENT
    105. \}
    106.  
    107. macro name#.SetPosition Value*, Relation, HighValue
    108. \{
    109.     if Relation eq
    110.         push FILE_BEGIN
    111.     else
    112.         pushd Relation
    113.     end if
    114.  
    115.     if HighValue eq
    116.         push 0
    117.     else
    118.         pushd HighValue
    119.     end if
    120.  
    121.     pushd Value
    122.     pushd [name#.Handle]
    123.     call [SetFilePointer]
    124.     \}
    125.  
    126. macro name#.FileSize
    127. \{
    128.     invoke GetFileSize, [name#.Handle], 0
    129. \}
    130.  
    131. macro name#.OpenRead Path*
    132. \{
    133.     name#.CreateFile Path, GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ
    134. \}
    135.  
    136. macro name#.OpenWrite Path*
    137. \{
    138.     name#.CreateFile Path, GENERIC_READ+GENERIC_WRITE, OPEN_EXISTING, FILE_SHARE_READ
    139. \}
    140.  
    141. macro name#.Append Path*
    142. \{
    143.     name#.CreateFile Path, GENERIC_WRITE, OPEN_ALWAYS
    144.     name#.SetPosition 0, FILE_END
    145. \}
    146.  
    147. macro name#.Create Path*
    148. \{
    149.     name#.CreateFile Path, GENERIC_WRITE, CREATE_ALWAYS, FILE_SHARE_READ
    150. \}
    Как им пользоваться? Очень просто!

    Код (Text):
    1.     TFile File      ;Создаем глобальный объект
    2.     File.Store      ;Сохраняем поля объекта в памяти
    3.  
    4.     _FileName DU 'FileName.txt',0
    5.     _TestStr            DB 'Hello',0
    6.     Buffer DB 256 DUP(0)
    7.    
    8.  
    9. ;Вот так легко и просто можно использовать объект в программе
    10. proc Main
    11.     File.OpenRead _FileName
    12.     File.Read Buffer, 256
    13.     File.Close
    14. ret
    15. endp
    16.  
    17. ;А сейчас я покажу как создавать локальный объект
    18. proc Check FileName
    19. TFile .fl   ;Имя объекта в результает получается как Check.fl
    20. local FileData[.fl.Size]:BYTE     ;Выделяем место в стеке под объект
    21. .fl.At FileData                                             ;Адресуем наш объект на выделенное место в стеке
    22.  
    23. .fl.Create [FileName]
    24. ;Это плохой способ работы со строками, в дальнейшем я покажу как работать со строками более эффективно
    25. .fl.Write _TestStr, 5                                  
    26. .fl.Close
    27. ret
    28. endp
    В чем преимущество использования данной техники?
    Я к примеру постоянно не могу с налету вспомнить какие параметры необходимы для передачи
    в CreateFile, чтобы получить необходимый результат. А с объектом TFile этот набор действий выполняется легко
    и непринужденно. А главное это никак не отразится на качестве выходного файла. Код будет таким же оптимальным.

    Если, прочитав эти два поста, вам понравилась данная техника, то я буду продолжать описание.
    Также я расчитываю на идеи, которые помогут сделать эту технику лучше.
     
  3. dead_body

    dead_body wasm.ru

    Публикаций:
    0
    Регистрация:
    3 сен 2004
    Сообщения:
    603
    Адрес:
    Украина;г.Харьков;г.Н.Каховка
    Miller Rabin
    Тема интересна, но сделай пожайлуста следуюющее, если не сложно:

    Откомпилируй проект с 10-100-1000-5000 обьектов и покажи сколько нужно памяти и времени.
     
  4. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    dead_body
    Я подсчитал :)
    В моем последнем проекте На fasm используется 4672 подобных объектов объектов. Я считаю и локальные внути процедур. Так как с точки зрения компилятора глобальные и локальные это одно и тоже.

    Время компиляции 1 секунда, для того чтобы проект скомпилировался необходимо в опции -m указать минимум 65535 килобайтов памяти.

    Я думаю что это не критерий. тем более что это всего-лишь память необходимая для компиляции проекта, а не память требуемая для его работы :)
     
  5. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    А если учесть что Вы не можете налету вспомнить какие параметры необходимы для передачи в эти объекты, и как они вообще называются? В случае с API всегда можно заглянуть в MSDN и быстро найти там всю нужную документацию, а на Ваши "объекты" документации нету. Конечно идея интересна, но ценность ее сомнительна.
     
  6. dead_body

    dead_body wasm.ru

    Публикаций:
    0
    Регистрация:
    3 сен 2004
    Сообщения:
    603
    Адрес:
    Украина;г.Харьков;г.Н.Каховка
    GoldFinch
    Составить небольшой текстовый документ никто не мешает - а потом и выучиться само, имхо.

    Miller Rabin
    Да, я уже и сам проверил с 10к обьектов - достаточно быстро, а память для компиляции это не сильно важный критерий.

    Как сделаю что-то выложу, вернее как оформлю в нормальный вид, а не под себя.
     
  7. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    GoldFinch
    Хех. Ну что же продолжаем защищаться дальше :)

    Вы неправильно поняли смысл данной фразы.
    Конечно, если забыл в каком порядке идут параметры в CreateFile и какой флаг как там называется, то это легко посмотреть в справке :). Хотя при данном способе даже в справку лезть не нужно все решается с налета
    File.Create _FileName
    File.Write Buffer, Buffer.Size
    File.Close
    В этом коде даже комментариев не нужно. Все читается легко. Это первый плюс
    Второй плюс заключается в том, что не нужно помнить все параметры, можно задать их по-умолчанию внутри метода.

    Отлично давайте рассмотрим другой пример.
    Создание просмотрщика буфера обмена.

    О том как его создавать подробно описано в МСДН, но это не одна и не две функции. Это целая последовательность действий в которой можно наплодить кучу ошибок. Однако если всю процедуру создания просмотрщика заключить в единый объект,то написав однажды, можно легко и быстро обращаться к нему как только он понадобится.

    TClipboardViewer Viewer ;Создаем объект просмотрщика
    Viewer.Store ;Сохраняем в памяти его поля

    proc Main
    ;OnClipboardChange пользовательская процедура, которая вызывается как только меняется содержимое буфера обмена
    mov [Viewer.OnClipboardChange], OnChange
    Viewer.Create ;Создаем окно просмотрщика и регистрируем его в цепочке Clipboard Viewer Chain
    ...
    endp

    ;В этой процедуре делаем что хотим с данными буфера обмена.
    proc OnChange pData, DataType, DataSize
    ....
    ret
    endp

    Теперь ценность понятна? Написав что-то однажды и заключив это в такой вот объект больше не нужно будет запоминать как он работает. А другие пользователи могут понять, что это за просмотрщик буфера и что он делает, не копаясь в вашем коде, а просто взглянув на объект и его методы :)
     
  8. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    dead_body
    У меня тоже есть библиотека подобных объектов. Но на мой взгляд глупо ее выкладывать. По-крайне мере сейчас.

    Я хотел бы сосредоточить внимание на самой концепции создания макросов. И возможно придумать нечто более лучшее, чем есть у меня.

    Затем сделать из всего этого единый хорошо читаемый материал и пусть люди пользуются. Мне кажется это было бы лучше чем просто выкинуть в раздел иходники очередную либу.
     
  9. Miller Rabin

    Miller Rabin New Member

    Публикаций:
    0
    Регистрация:
    4 янв 2006
    Сообщения:
    185
    Продолжаю развивать тему. Хочу привести очень простой макрос по работе с таблицами строк в Fasm

    macro TAnsiStringTable [name, Value]
    {
    forward
    name db Value
    db 0
    name#.Size = $-name-1
    }

    Данный макрос удобен для работы с таблицами строк. Пользоваться им можно вот так:

    TAnsiStringTable _Str1, 'Hello',\
    _Str2, 'World'

    А затем обращаться к строке к примеру так
    mov eax, _Str1
    mov ecx, _Str1.Size

    Также есть не менее интересный макрос, для создания массивов указателей строк

    macro TAnsiStringArray name, [Values]
    {
    common
    label name DWORD
    forward
    local Str
    dd Str
    common
    dd 0
    forward
    Str db Values,0
    }

    Данный макрос создает именованный массив указателей на строки\
    Пользоваться им можно так:
    TAnsiStringArray TestArray, 'Hello',\
    'World'
    Отличается от TAnsiStringTable расположением строк в памяти. Сначала идет массив указателей на строки, а ниже сами строки, на которые они указывают. Данный макрос удобен для решения задач, когда доступ к строке необходимо организовать по ее индексу.
     
  10. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    А сколько "лишнего" кода вносят ваши макросы?
    Не будет ли проблематично отлаживать эти программы в отладчике?
     
  11. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    И еще вопрос.Есть ли в "природе", программа что ли,для написания макросов для FASM,
    которая показывает что в результате роботы макроса компилирует компилятор.
    Я хочу сказать что макрос типа:
    macro plus arg1,arg2
    {
    add arg1,arg2
    }
    Понятен,а что получится в результате:
    macro name#.Read Buffer*, Length*, Bytes, Overlapped
    \{
    if Overlapped eq
    push 0
    else
    push Overlapped
    end if
    if Bytes eq
    pushd esp
    else
    pushd Bytes
    end if
    pushd Length
    pushd Buffer
    pushd [name#.Handle]
    call [ReadFile]

    \}

    уже сложнее,и это не самый сложный макрос.
     
  12. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Юзай fasmpre, еще давно с flatassembler.net скачивал
     
  13. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    Спасибо за программу,попробую.
     
  14. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    Asvald не могли бы вы подробней описать роботу с FASMPRE.
    Хоть один пимерчик.:)
     
  15. Asvald

    Asvald New Member

    Публикаций:
    0
    Регистрация:
    18 сен 2006
    Сообщения:
    58
    Используется например так fasmpre my.asm my.txt
    обрабатывает он только препроцессорные директивы, стадия ассемблирования не выполняется, в выходном файле my.txt будет то, что полноценный fasm.exe начал бы потом ассемблировать.
     
  16. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    Не работает.:dntknw:(
     
  17. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    Sashok, возможно, это старый препроцессор (не качал).

    Сейчас всё поддерживается официально: возьми последний фасм с офсайта (1.69.12 сейчас), в папке TOOLS\WIN32 собери PREPSRC.ASM, положи результат в папку с fasm.exe и пользуйся:
    .fas-файл ещё можно из fasmw собрать по Run->Build symbols (Ctrl+F8), но выдирать из него препроцессированный исходник всё равно придётся через командную строку.
     
  18. Z3N

    Z3N New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    812
    2Miller Rabin

    Считаю, что вы делаете хорошее дело. А с уровнем современных IDE вы можете забить на MSDN. Они же показывают "нужные" параметры при вызове ф-ии. В том же SE, который я активно изучаю, можно сделать подбор "нужных" параметров и для своих объектов (как вы их называете), а так же SE держит явадок и поэтому если вы прокомментируете ф-ю по правилам явадок, то при вводе параметров вам покажут хтмл справку.
     
  19. Sashok

    Sashok New Member

    Публикаций:
    0
    Регистрация:
    19 янв 2009
    Сообщения:
    52
    Прошу прощения уважаемый Miller Rabin за то что отклоняю народ от вашей темы но хотел бы спросить
    у iZzz32 ,не знает ли он случайно что за утилиты лежат в Flat assembler 1.69.12\TOOLS\WIN32,
    а именно LISTING и SYMBOLS.
    Кстати FASMPRE заработала. :)))
     
  20. Z3N

    Z3N New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    812
    По-моему, самым логичным решением было бы скомпилировать их и посмотреть, что же они делают.

    Хотя смею предположить, что результатом работы первой программы станет полный асм листинг, а вторая покажет все переменные, использованные в программе.

    Вообще-то странно, что ты сюда запостил, ты посмотри на дату первого поста, судя по всему мы так и не дождёмся этих макросов. Интересно, что же случилось с автором. Попробую написать ему в личку.