Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа 4.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
117.91 Кб
Скачать

Уникальность меток при макрорасширениях

В макросах могут встречаться метки. Вот, например, макрос, который устанавливает флаги процессора в соответствии со значением параметра, а затем, если флаг знака S != 1 (старший бит равен 0, это значит, что если число рассматривать как знаковое, то оно положительное), то следует «перепрыгивание» на метку (число положительное, делать ничего не надо), а иначе число преобразуется в такое же, но с противоположным знаком. Короче, это вычисление абсолютной величины параметра:

Absval MACRO param

test param, param

jns metka

neg param

metka:

EMDM

В этом макросе кроется принципиальная ошибка. Суть её в том, что сколько раз будет произведена макрорасширение Absval, столько раз в исходный текст будет подставлена метка metka: . Мы помним, что метки – это адресные константы, равные адресу (смещению) метки в секции кода. Если в программе окажутся одинаковые метки в разных местах программы, то компилятор не разберётся с этой проблемой: у адресной константы не может быть одновременно несколько разных значений. Результат очевиден – компиляция прерывается с ошибкой «Повторяющиеся метки».

Выход из этой ситуации прост. Пусть макрогенератор сам «выдумывает» уникальные имена меток при выполнении макрорасширений. Чтобы он это стал делать, надо объявить встречающиеся в теле макроса метки как «локальные». Это надо написать сразу после заголовка макроопределения:

Absval MACRO param

LOCAL metka

test param, param

jns metka

neg param

metka:

EMDM

Теперь макровызов Absval EDX будет расширено в

test EDX, EDX

jns ??0000

neg EDX

??0000:

Второй макровызов, пусть это будет Absval AL,будет расширен в

test AL, AL

jns ??0001

neg AL

??0001:

Имена ??0000 и ??0001 – это и есть уникальные имена меток, которые сочинил сам макрогенератор. Компилятор образует их из буквенной строки «??» и лепит справа символьную 16-ричную запись номера метки в диапазоне от 0000 до FFFF. (Известно, что символ ? в ассемблере рассматривается как буква, поэтому искусственные имена ??0000, ??0001 и т.д. синтаксически совершенно корректны). Номер увеличивается на 1 при каждом новом макрорасширении. Поучается, что макрогенератор в одной программе способен создать 0FFFFh = 65536 искусственных меток. Такое возможное их количество перекрывает все мыслимые практические потребности.

Макроконстанты

Макроконстанта определяется с помощью ключевого слова EQU (от слова equivalence – равносильно). Например

One equ 2*3

Username equ 1024/8

Понимать это нужно так: макрогенератор строку «One» везде заменит на результат вычисления выражения 2*3, а строку «Username» - на результат вычисления выражения 1024/8. Единожды определив такие числовые макроконстанты, переопределить их потом нельзя. Замены имён макроконстант на строки-значения производятся в исходном тексте в строках, расположенных ниже определения. Поэтому макроконстанты нужно определять в самом начале asm-файлов.

Макропеременные и макровычисления

Макропеременные могут быть только целочисленными. Они создаются на период компиляции с помощью операции = (знак равенства). Значение константы в процессе компиляции можно переопределять сколько угодно раз. Например

MyVar = 10

Это переменные, с которыми работает компилятор ML как любое приложение работает со своими переменными. Компилятор может в процессе трансляции выполнять много вычислительных операций. В том числе можно программировать циклы, проверки условий. Рассмотрим некоторые примеры.

Создание в секции данных описания числового массива из десяти квадратов первых десяти целых чисел.

.data

A=1

Massiv Label Word

Repeat 10

Dw A*A

A = A+1

Endm

Макрогенератор создаст следующее:

.data

A=1

Massiv Label Word

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Dw A*A

A = A+1

Все вычисления выполнятся в период трансляции. Здесь же мы наблюдаем работу только макрогенератора, а он, как говорилось выше, манипулирует только текстами.

Пример – записать через цикл операторы сохранения в стек регистров, чьи имена заканчиваются на X:

irpc rg, ABCD

push rg&X

endm