Макрос в фасме (implib)

Тема в разделе "WASM.PROJECTS", создана пользователем Quantum, 2 ноя 2006.

  1. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Пытаюсь сделать следующее:
    Код (Text):
    1. counter = 0
    2. dd counter
    3.  
    4. macro some_macro [args] {
    5.    counter = counter + 1
    6.    ; тут, собственно, следует тело "архиполезного" макроса :)
    7. }
    Далее в коде вызывается мой макрос произвольное кол-во раз. Как вы уже все догадались, я пытаюсь сохранить в том самом первом dd кол-во раз, которое был вызван макрос. Например, если юзер вызвал some_macro 5 раз, dd counter должен сгенерировать в бинарнике пятёрку. Естественно, этот код не работает и всегда сохраняет туда ноль (и я знаю почему, но решил привести этот код для наглядности). Если я правильно понимаю философию фасма, должен быть способ реализовать данный код без использования store в теле макроса или я ошибаюсь?
     
  2. dead_body

    dead_body wasm.ru

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

    или нет?
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    dead_body
    Там условие - присваивание после последнего использование. Было бы интереснее обойти это.

    Как обойти не придумал, но никто не запрещает в тело макроса встроить подобное:
    Код (Text):
    1. macro inc_cnt
    2. {
    3.   local cnt
    4.   load cnt dword from counter
    5.   store dword cnt+1 at counter
    6. }
    7.  
    8. counter dd 0
    9.  
    10. macro some
    11. { inc_cnt
    12.    ...
    13. }
     
  4. dead_body

    dead_body wasm.ru

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

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Quantum

    ты же инициализируешь счетчик (counter = 0) и сразу определяешь (dd counter), на тот момент он и равен нулю (а откуда фасм знает, толи ты туда ноль хотел затолкнуть - толи пятерку), если перенести определение (dd counter) после пяти вызовов some_macro, то там будет 5, а чтобы не переносить можно ещё взять одну переменную
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Мужики, что-то вы невнимательно прочитали первый пост.

    IceStudent
    store нельзя юзать (см. условие)

    bogrus
    Я же написал, что знаю почему этот код не работает, но привёл именно этот вариант для наглядности.

    Т.е. примерно так:
    Код (Text):
    1. counter = 0
    2. dd some_var
    3.  
    4. macro some_macro [args] {
    5.    counter = counter + 1
    6.    ; тут, собственно, следует тело "архиполезного" макроса :)
    7. }
    И где-то в самом конце листинга, после всех вызовов some_macro, дописать some_var = counter. Такой вариант не годится, т.к. дописывать лишнюю строчку в основном листинге нельзя (т.е. можно, конечно, но не приветствуется). Если бы в макросе можно было установить, что его вызвали в последний раз...

    dead_body
    Что за наезд? :) Я ваш мануал наизусть уже знаю - вчера целый день читал и перечитывал. И про философию фасма тоже читал.

    all
    Вот чуть более полная версия задачи:
    Код (Text):
    1. counter = 0
    2. times counter dd 0 ; вот почему store не катит
    3.  
    4. macro some_macro [args] {
    5.    counter = counter + 1
    6.    ; тут, собственно, следует тело "архиполезного" макроса :)
    7. }
     
  7. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Quantum
    Сразу бы так. Собственно, в таких случаях вариант с двумя переменными и используют.

    Это невозможно.
     
  8. dead_body

    dead_body wasm.ru

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

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    dead_body
    А как? Первый раз легко определить, можно также объявить переменную, если она не была объявлена. Но как определить последний вызов?
     
  10. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    IceStudent
    Это ещё далеко не всё :)

    Попутно созрел ещё один вопрос. Пытаюсь сгенерировать такую табличку указателей:
    dd some_ptr1, some_ptr2, some_ptr3

    И т.д. Указателей может быть любое количество. Имена я проиндексировал начиная с 1, но можно и с нуля - это не важно. Количество указателей - это тот самый counter из первого примера, т.е. вычисляется на протяжении всей компиляции. Попробовал так:
    Код (Text):
    1. times counter dd some_ptr%
    Препроцессор ругается и не замещает % на { 1, 2, 3 ... }

    Попробовал через # % - тоже самое. rept не катит, т.к. счётчик вычисляется динамически.

    И сразу ещё одна проблема. Дело в том, что этикетки some_ptrN задаются в макросе some_macro, примерно так:
    Код (Text):
    1. macro some_macro [args] {
    2. local counter2
    3.     counter=counter+1
    4.     counter2=counter
    5. some_ptr#counter2:
    6. ; далее идёт код
    Во-первых, не понятно почему я тут не могу использовать counter напрямую для формирования имени этикетки, а вынужден обьявлять ещё одну переменную. Во-вторых, хотя этот код исправно собирается, этикетки some_ptr1, some_ptr2 и т.д. не создаются, или они недоступны извне макроса... Вроде, типичная задача, но что-то не получается добить.
     
  11. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Quantum
    Нужно различать работу препроцессора и ассемблера. Макросы, склеивание имён - это работа первого. Константы - второго. В мануале это разнесено по главе 2.2 и 2.3, а описано в 2.3.7.

    В твоём случае думаю проще будет обратиться к примерам. Там выделяется место под таблицу переходов и потом она заполняется. Сделано это на вложенных макро.

    А в твоём случае "store" как раз можно использовать, для позднего заполнения таблицы указателями. Проблема лишь в генерации имён указателей в такой постановке задачи.

    Вообще, лучше сразу давать все условия :)
     
  12. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Есть ещё подход (правда игрался я с ним в МАСМе), но идея вроде-бы компиляторонезависима ;)
    1. Создаётся текстовая строка (одна для всех макросов) в которую записываются отложенные команды, если команд много, то строка разбивается на несколько и добавляется счётчик строк (всё это легко сложить в макрос генерирующий отложенную команду)
    2. команда типа times counter dd 0 заносится в список отложенных при первом вызове архиполезного макроса, соответственно другие макросы могут дописать в эту строку свои отложенные команды
    3. в конце основного листинга добавляется макрос заставляющий компилятор обработать этот список отложенных команд.
    В отличие от некрасивого добавления самого times counter dd 0 в конец спец макрос унивесален и может быть приравнен к директиве окончания листинга ;), а при отсутствии отложенных команд, он соответственно ничего не делает и никому не мешает ;).
     
  13. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    IceStudent
    Ясно. Думаю, что смогу сделать также.

    Добавил: Получилось!!! Спасибо за ссылку!

    После той таблицы идёт ещё одна с вообще неописуемым форматом :) Я пытаюсь установить как далеко можно уехать на одном препроцессоре фасма, поэтому решаю задачу по частям :)

    Y_Mur
    Такая идея у меня тоже возникла и, возможно, понадобится для решения более сложной задачи (следующий этап). Если есть какие-то наработки на фасме - прошу поделиться ;)
     
  14. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Сортировка на макросах? Хеширование? Конечные автоматы? :)

    Далеко..

    Y_Mur
    Интересный подход. Нечто подобное используется в символьных обработках в макросах (т.н. equ-списки), весьма мощное решение, но трудноотлаживаемое :)
     
  15. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    IceStudent
    Лексикографическая! Ага, это мне тоже нужно для следующего этапа. Как ты угадал?!

    Пока не надо

    Пока не надо

    Удивительно, но генератор библиотек импорта в противовес масмовскому inc2l практически готов!

    Поэтому я больше ценю функциональный подход и именно поэтому стараюсь не использовать load/store
     
  16. dead_body

    dead_body wasm.ru

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

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Quantum
    Лексигографическая? Хех. Ну напиши условия, попробую.

    dumpbin + perl. Или ты для масма?
     
  18. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    dead_body
    IceStudent
    Для масма и других линкеров с поддержкой COFF. Например, ALINK не дружит с масмовскими либами - такой утиль может быть полезен для насмовцев. inc2l не поддерживает импорт по ординалу и создание общей либы сразу для нескольких DLL - это тоже учтено. Стандартный микрософтовский префикс __imp_ в именах символов из dll иногда вызывает конфликты в некоторых компиляторах ЯВУ, которые используют polink в качестве бакэнда - это тоже учтено. Поддержка не совсем стандартных имён функций с переименованием, типа '123', которые не поддерживаются масмом. В общем, стараюсь учесть все минусы, которые обнаружил в других утилитах :)

    IceStudent
    Сначала я сам попробую.
     
  19. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Выкладываю то, что получилось. В архиве:

    implib.inc - тот самый макрос ;)
    dsound.asm - примерчик использования. Создаёт более полную версию dsound.lib, чем та, что поставляется с масмом. Показывает возможность импорта по ординалу.
    make.bat - обычный батник, который запускает фасм, скармливает ему dsound.asm и выдаёт dsound.lib.

    Попробовал на разных версиях линкеров:

    polink - всё OK
    ms link - нужно включать опцию /OPT:NOREF, иначе импорт получается битый. Пока не очень понятно из-за чего такое происходит, но я это пофиксю. Может, из-за того, что обьектник, состоящий из одних комдатов, линкером опускается по умолчанию.
     
  20. dead_body

    dead_body wasm.ru

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