Низкоуровневое программирование для Дzenствующих
Вид материала | Документы |
СодержаниеIII.1. Функционирование макросов |
- Низкоуровневое программирование, 108.99kb.
- Курс является базовым как для изучения других математических дисциплин, так и для более, 36.89kb.
- 1 Обобщенное программирование. Обобщенное программирование это еще одна парадигма программирования,, 55.18kb.
- Введение в линейное программирование линейное программирование (ЛП), 139.72kb.
- Учебно-методический комплекс для студентов заочного обучения специальности Прикладная, 63.23kb.
- Аттестационное тестирование в сфере профессионального образования, 72.49kb.
- Лекции по дисциплине «Социальное моделирование и программирование», 44.69kb.
- Программа дисциплины Линейное программирование Семестр, 17.93kb.
- Программа дисциплины "Программирование" для направления, 488.76kb.
- Рабочая программа по дисциплине Программирование на языке высокого уровня для специальности, 182.97kb.
III.1. Функционирование макросов
Чтобы строить макросы, важно понимать, как они работают, и как их обрабатывает MASM. Давайте рассмотрим типичный макро, и этапы его обработки.
MyMacro macro param1,param2,param3:VARARG
echo param1
echo param2
echo param3
endm
MyMacro Параметр 1, Параметр 2, Параметр 3, Параметр 4
;; Вывод -=-=-=-=-=-=-=-=
Параметр 1
Параметр 2
Параметр 3,Параметр 4
1. Компилятор встречает лексему MyMacro
2. Он проверяет, содержится ли эта лексема в словаре ключевых слов
3. Если нет, то он проверяет, содержится ли эта лексема в списке макросов.
4. Если да, он передаёт текст, содержащийся в макро препроцессору. Препроцессор заменяет все вхождения формальных параметров в этом тексте на их значения. В данном случае мы имеем:
echo Параметр 1
echo Параметр 2
echo Параметр 3,Параметр 4
5. Препроцессор возвращает компилятору обработанный текст, который после компилируется.
Обратите внимание на пункт 4 и 5. Они ключевые. Очень часто при работе с макроопределениями появляются ошибки из-за неверного понимания порядка генерирования макро текста. Например:
PROGRAM_IMAGE_BASE EQU 400000h
FunMacro macro
exitm <Параметр 3,параметр 4>
endm
MyMacro macro param1,param2,param3:VARARG
echo param1
echo param2
echo param3
endm
MyMacro PROGRAM_IMAGE_BASE, FunMacro(),Параметр 5
А теперь самостоятельно опишите порядок действий компилятора при вызове этого макро. Запишите его себе куда-нибудь, так чтобы сравнить, и смотрите на вывод:
PROGRAM_IMAGE_BASE
Параметр 3, Параметр 4
Параметр 5
Прежде чем объяснять действительный порядок, я оговорюсь, что директива echoникогда не обрабатывает определённые константы, такие как PROGRAM_IMAGE_BASE.
Это утверждение справедливо даже тогда, когда перед директивой echo стоит оператор %, который может раскрывать только текстовые макроопределения. То есть выражение:
echo FunMacro()
Даст результат:
FunMacro()
Теперь, когда мы немного порассуждали можно привести тот текст, который генерируется из макро:
echo PROGRAM_IMAGE_BASE
echo Параметр 3, Параметр 4
echo Параметр 5
Это означает следующее:
- При вызове макро, значение формальных параметров воспринимается как текст, и передаётся в макро как строка.
- Исключение составляют лишь макрофункции, результат выполнения которых вычисляется и присваивается значению параметра.
Специальный оператор % заставляет ассемблер вычислять текстовую строку, следующую за ним, и только потом подставлять в правое выражение. Например, если мы перепишем макровызов так:
MyMacro %PROGRAM_IMAGE_BASE, FunMacro,Параметр 5
То получим вывод:
4194304 ;; Значение PROGRAM_IMAGE_BASE
Параметр 3, Параметр 4
Параметр 5
Давайте рассмотрим ещё один пример, который хорошо показывает, как работает макро. Например, вы определили макропроцедуру (именно его, а не макрофункцию). То когда вы пишите такое:
@Macro что-то, что придёт вам в голову [символ возврата каретки]
Что делает препроцессор ML:
1. Считывает всю строку до символа возврата каретки;
2. Смотрит, как вы определили параметры в макро;
3. Сканирует строку на наличие символа «,» или «<», «>»;
Вам может показаться странным, но препроцессору всё равно, какие символы идут во время вызова макро. То есть вы можете вызвать макро так: @MyMacro Привет, это кириллица в файле,\ и ML не будет на неё ругаться или @MyMacro !@#$%&*(){}[] Посмотрите как СИльно (от буквы CИ) будет выглядеть макро в MASM: MyMacro{Это что С++?} MyMacro[Нет, это MASM] |
4. Назначает формальным параметрам (любого типа, кроме VARARG) макро участки строк, которые были определены разделителями запятыми (предварительно очистив от хвостовых и начальных пробелов, если только строка не была определена в угловых кавычках <>);
5. Если макро содержит формальный параметр типа VARARG, то ML сперва инициализирует значениями (согласно пункту 4) обычные формальные параметры, и только потом назначает параметру типа VARARG (который может быть только один в конце списка параметров) всю строку до конца.
-= Обратите внимание =- |
Если вы пишите макровызов как @Macro Param1 , Param2 То значение параметров будут: param1 = «Param1» param2 = «Param2» Если вы хотите передать сами значения строк, то должны заключит их в угловые кавычки: @Macro < Param1 >,< Param2 > |
6. Препроцессор разрешает все вызовы макрофункций, если они есть в лексемах параметра, и присваивает их результат соответствующему параметру. Если лексему в строке параметра предваряет символ %, то он вычисляет её значение до того, как передаст строку внутрь макро.
-= Обратите внимание =- |
Благодаря именно такому порядку: 1. Разделение строки на макропараметры 2. Поиск и Вызов макрофункций в значениях макропараметров 3. Присвоение результатов соответствующему макропараметру в следующем случае: MyMacro macro param1,param2,param3 echo param1 endm -------------------------------------- FunMacro macro param:VARARG exitm param endm MyMacro FunMacro(param1, param2, param3) OUT: param1, param2, param3 -------------------------------------- строка, возращаемая макрофункцией присваивается параметру param1, а не param2, param3 |
Теперь вы в состоянии объяснить следующую ситуацию:
MyMacro macro
…
endm
MyMacro()
Предупреждение при компиляции:
: warning A4006: too many arguments in macro call
Как нужно было бы изменить этот макро (именно макро, а не макрофункцию), чтобы предупреждение не выдавалось? А почему оно происходит?
Если вы с лёгкостью ответили на этот вопрос, значит, материал усвоен, иначе советую ещё раз прочитать его, и ответить на следующий вопрос.
Как должен понять компилятор следующий код:
MyMacro macro param1
param1
endm
MyMacro = 2
Естественно отвечать на этот вопрос вы должны без помощи компилятора (то есть проверить компиляцией). Если вы не можете ответить на этот вопрос, или неуверенны в верности ответа, я поменяю задание:
MyMacro macro param1
echo param1
endm
MyMacro = 2
Запустите его в ML. Если и теперь вы сомневаетесь – перечитайте этот пункт снова и снова, продолжая экспериментировать.