Пытаюсь сделать следующее: Код (Text): counter = 0 dd counter macro some_macro [args] { counter = counter + 1 ; тут, собственно, следует тело "архиполезного" макроса :) } Далее в коде вызывается мой макрос произвольное кол-во раз. Как вы уже все догадались, я пытаюсь сохранить в том самом первом dd кол-во раз, которое был вызван макрос. Например, если юзер вызвал some_macro 5 раз, dd counter должен сгенерировать в бинарнике пятёрку. Естественно, этот код не работает и всегда сохраняет туда ноль (и я знаю почему, но решил привести этот код для наглядности). Если я правильно понимаю философию фасма, должен быть способ реализовать данный код без использования store в теле макроса или я ошибаюсь?
dead_body Там условие - присваивание после последнего использование. Было бы интереснее обойти это. Как обойти не придумал, но никто не запрещает в тело макроса встроить подобное: Код (Text): macro inc_cnt { local cnt load cnt dword from counter store dword cnt+1 at counter } counter dd 0 macro some { inc_cnt ... }
Quantum ты же инициализируешь счетчик (counter = 0) и сразу определяешь (dd counter), на тот момент он и равен нулю (а откуда фасм знает, толи ты туда ноль хотел затолкнуть - толи пятерку), если перенести определение (dd counter) после пяти вызовов some_macro, то там будет 5, а чтобы не переносить можно ещё взять одну переменную
Мужики, что-то вы невнимательно прочитали первый пост. IceStudent store нельзя юзать (см. условие) bogrus Я же написал, что знаю почему этот код не работает, но привёл именно этот вариант для наглядности. Т.е. примерно так: Код (Text): counter = 0 dd some_var macro some_macro [args] { counter = counter + 1 ; тут, собственно, следует тело "архиполезного" макроса :) } И где-то в самом конце листинга, после всех вызовов some_macro, дописать some_var = counter. Такой вариант не годится, т.к. дописывать лишнюю строчку в основном листинге нельзя (т.е. можно, конечно, но не приветствуется). Если бы в макросе можно было установить, что его вызвали в последний раз... dead_body Что за наезд? Я ваш мануал наизусть уже знаю - вчера целый день читал и перечитывал. И про философию фасма тоже читал. all Вот чуть более полная версия задачи: Код (Text): counter = 0 times counter dd 0 ; вот почему store не катит macro some_macro [args] { counter = counter + 1 ; тут, собственно, следует тело "архиполезного" макроса :) }
Quantum Сразу бы так. Собственно, в таких случаях вариант с двумя переменными и используют. Это невозможно.
dead_body А как? Первый раз легко определить, можно также объявить переменную, если она не была объявлена. Но как определить последний вызов?
IceStudent Это ещё далеко не всё Попутно созрел ещё один вопрос. Пытаюсь сгенерировать такую табличку указателей: dd some_ptr1, some_ptr2, some_ptr3 И т.д. Указателей может быть любое количество. Имена я проиндексировал начиная с 1, но можно и с нуля - это не важно. Количество указателей - это тот самый counter из первого примера, т.е. вычисляется на протяжении всей компиляции. Попробовал так: Код (Text): times counter dd some_ptr% Препроцессор ругается и не замещает % на { 1, 2, 3 ... } Попробовал через # % - тоже самое. rept не катит, т.к. счётчик вычисляется динамически. И сразу ещё одна проблема. Дело в том, что этикетки some_ptrN задаются в макросе some_macro, примерно так: Код (Text): macro some_macro [args] { local counter2 counter=counter+1 counter2=counter some_ptr#counter2: ; далее идёт код Во-первых, не понятно почему я тут не могу использовать counter напрямую для формирования имени этикетки, а вынужден обьявлять ещё одну переменную. Во-вторых, хотя этот код исправно собирается, этикетки some_ptr1, some_ptr2 и т.д. не создаются, или они недоступны извне макроса... Вроде, типичная задача, но что-то не получается добить.
Quantum Нужно различать работу препроцессора и ассемблера. Макросы, склеивание имён - это работа первого. Константы - второго. В мануале это разнесено по главе 2.2 и 2.3, а описано в 2.3.7. В твоём случае думаю проще будет обратиться к примерам. Там выделяется место под таблицу переходов и потом она заполняется. Сделано это на вложенных макро. А в твоём случае "store" как раз можно использовать, для позднего заполнения таблицы указателями. Проблема лишь в генерации имён указателей в такой постановке задачи. Вообще, лучше сразу давать все условия
Есть ещё подход (правда игрался я с ним в МАСМе), но идея вроде-бы компиляторонезависима 1. Создаётся текстовая строка (одна для всех макросов) в которую записываются отложенные команды, если команд много, то строка разбивается на несколько и добавляется счётчик строк (всё это легко сложить в макрос генерирующий отложенную команду) 2. команда типа times counter dd 0 заносится в список отложенных при первом вызове архиполезного макроса, соответственно другие макросы могут дописать в эту строку свои отложенные команды 3. в конце основного листинга добавляется макрос заставляющий компилятор обработать этот список отложенных команд. В отличие от некрасивого добавления самого times counter dd 0 в конец спец макрос унивесален и может быть приравнен к директиве окончания листинга , а при отсутствии отложенных команд, он соответственно ничего не делает и никому не мешает .
IceStudent Ясно. Думаю, что смогу сделать также. Добавил: Получилось!!! Спасибо за ссылку! После той таблицы идёт ещё одна с вообще неописуемым форматом Я пытаюсь установить как далеко можно уехать на одном препроцессоре фасма, поэтому решаю задачу по частям Y_Mur Такая идея у меня тоже возникла и, возможно, понадобится для решения более сложной задачи (следующий этап). Если есть какие-то наработки на фасме - прошу поделиться
Сортировка на макросах? Хеширование? Конечные автоматы? Далеко.. Y_Mur Интересный подход. Нечто подобное используется в символьных обработках в макросах (т.н. equ-списки), весьма мощное решение, но трудноотлаживаемое
IceStudent Лексикографическая! Ага, это мне тоже нужно для следующего этапа. Как ты угадал?! Пока не надо Пока не надо Удивительно, но генератор библиотек импорта в противовес масмовскому inc2l практически готов! Поэтому я больше ценю функциональный подход и именно поэтому стараюсь не использовать load/store
dead_body IceStudent Для масма и других линкеров с поддержкой COFF. Например, ALINK не дружит с масмовскими либами - такой утиль может быть полезен для насмовцев. inc2l не поддерживает импорт по ординалу и создание общей либы сразу для нескольких DLL - это тоже учтено. Стандартный микрософтовский префикс __imp_ в именах символов из dll иногда вызывает конфликты в некоторых компиляторах ЯВУ, которые используют polink в качестве бакэнда - это тоже учтено. Поддержка не совсем стандартных имён функций с переименованием, типа '123', которые не поддерживаются масмом. В общем, стараюсь учесть все минусы, которые обнаружил в других утилитах IceStudent Сначала я сам попробую.
Выкладываю то, что получилось. В архиве: implib.inc - тот самый макрос dsound.asm - примерчик использования. Создаёт более полную версию dsound.lib, чем та, что поставляется с масмом. Показывает возможность импорта по ординалу. make.bat - обычный батник, который запускает фасм, скармливает ему dsound.asm и выдаёт dsound.lib. Попробовал на разных версиях линкеров: polink - всё OK ms link - нужно включать опцию /OPT:NOREF, иначе импорт получается битый. Пока не очень понятно из-за чего такое происходит, но я это пофиксю. Может, из-за того, что обьектник, состоящий из одних комдатов, линкером опускается по умолчанию.