- •Методические указания
- •«Моделирование программы гипотетической машины с помощью макросредств»
- •1.Введение.
- •2.Пример выполнения курсовой работы.
- •2.1.Задание.
- •2.2.Анализ задачи и разработка алгоритма.
- •2.3.Разработка программы для гм.
- •2.3.1. Определение данных.
- •2.3.2.Определие команд гм.
- •2.4.Моделирование программы гм на реальной эвм.
- •2.4.1.Выборка и запиь слов гм.
- •2.4.2. Макроопрделения для команд гм.
- •2.5.Технология подготовки программы к выполнению и ее отладка.
- •2.6. Результаты работы программы
- •3. Варианты курсовой работы
- •4.Приложения
- •2. Блоки повторения
- •2.1. Rept-блоки
- •Irpc-блоки
- •2.4 Макрооператоры
- •3. Макросы
- •113.1. Макроопределения
- •3.1. Макрокоманды
- •3. 3. Макроподстановки и макрорасширения
- •3. 5. Макросы и процедуры
- •3. 6. Определение макроса через макрос
- •3.7. Директива local
- •113.8. Директива ехiтм
- •3. 9. Переопределение и отмена макросов
- •4. Условное ассемблирование
- •4. 1. Директивы if и ife
- •4.2. Операторы отношения. Логические операторы
- •4.3. Директивы ifidn ,ifdif , ifb и ifnb
4. 1. Директивы if и ife
Эти директивы имеют следующий вид:
IF <константное выражение>
IFE <константное выражение>
Встречая любую из этих директив , макрогенератор вычисляет указанное к ней константное выражение. В директиве IF условие считается вычисленным, если значение выражения отлично от 0, а директиве IFE ( if equal, если равно ) – если значение равно 0. Рассмотрим следующий пример. Предположим, что мы отлаживаем программу и для этого вставляем в определенные места ее текста отладочные печати (ОП), т.е. печать промежуточных значений каких-то переменных. Закончив отладку, мы, естественно, убираем ОП из текста. Но может оказаться так, и это действительно часто случается, что затем в программе опять появятся ошибки, и чтобы их найти, нам придется вставить те же ОП, а после исправления ошибок - снова удалить. И этот процесс вставки и удаления ОП может продолжаться долго. Вставлять и убирать ОП мы можем, конечно, сами с помощью какого-нибудь текстового редактора. Но если ОП много , если они разбросаны по всей программе, то такие изменения текста займут много времени, а кроме того, здесь легко и ошибиться – мы можем не туда вставить ОП или можем убрать из текста не то , что надо. Так вот, в подобной ситуации как раз и удобно использовать возможности условного ассемблирования: в тексте программы постоянно сохраняем ОП , но перед каждой из них указываем условие , что команды ОП должны оставаться в окончательном тексте программы только при отладке. Конкретно это можно сделать так. Договоримся, что режим прогона программы (отладка или счет) указывается с помощью константы DEBUG (отладка), которую описываем в начале текста программы и которой присваиваем значение 1, если у нас сейчас отладка:
DEBUG EQU 1
или значение 0 при счете:
DEBUG EQU 0
Тогда участок исходной программы с отладочной печатью (скажем, переменной Х) должен быть записан так, как указанно слева, в окончательном же тексте программы этот участок будет выглядеть так, как изображено справа:
. . .
. . . DEBUG<>0 MOV X, AX
MOV X, AX ─────────> OUTINT X
IF DEBUG MOV BX, 0
OUTINT X . . .
ENDIF
MOV BX,0 DEBUG=0 . . .
. . . ─────────> MOV X, AX
MOV BX, 0
. . .
При таком построении текста программы нам достаточно перед ее прогоном менять лишь одну строчку – описание константы DEBUG, чтобы макрогенератор формировал разный окончательный текст программы (с ОП или без них). Менять что-либо еще в тексте программы нам уже не надо. Здесь следует обратить внимание на такую вещь. Сделать так, чтобы ОП выполнялись при отладке и не выполнялись при счете , можно и с помощью команд условного перехода. Выглядит это примерно так :
. . .
MOV X, AX
CMP отладка ?
JNE L
OUTINT X
L: MOV BX,0
. . .
Казалось бы , получили то же самое решение проблемы. Однако это далеко не так. В чем же разница? В том, что в последнем случае команды ОП остаются в программе всегда, нужны они или нет, и потому всегда будут занимать место в памяти. Кроме того, здесь поверка, выполнять команды или нет, делается в процесс выполнения программы, и на это тратится время. При условном же ассемблировании команды ОП, если они не нужны, будут удалены из программы и потому не будут занимать место в памяти. Кроме того, здесь проверка, оставлять команды ОП или нет, осуществляется еще до того, как программа начнет выполняться, и потому в процессе выполнения программы никаких проверок и обходов уже не будет. Таким образом, при условном ассемблировании затрачивается больше времени на трансляцию программы, зато сама программа получится более экономной и по памяти, и по времени. В этом и заключается преимущество условного ассемблирования перед использованием команд условного перехода.
Рассмотрим еще один пример на использование директив IF и IFЕ, в котором средства условного ассемблирования используются не самостоятельно, как в предыдущем примере, а для описания макросов, что является основным случаем применения этих средств.
Опишем в виде макроса SHIFT Х,N операцию сдвига Х на N разрядов вправо при условии, что параметр Х - это имя какой-то переменной, а N - явно заданное положительное число, и при условии, что макрорасширение этого макроса должно содержать минимально возможное число команд.
Последнее условие означает, что по макрокоманде SHIFT X,N при N=1 должно формироваться макрорасширение из одной команды (SНR Х,1), а при N>1 - из двух команд (МОV CL,N и SHR Х,СL). Поскольку здесь в зависимости от некоторого условия (величины N) в окончательный текст программы (в макрорасширение) должны попадать разные фрагменты, то ясно, что при описании макроса следует воспользоваться средствами условного ассемблирования. Сделать это можно, например, так:
SHIFT MACRO X,N
IFE N-1 ;; N-1=0 ? (N=1 ?)
SHR X,1
ELSE ;;N>1
MOV CL,N
SHR X,CL
ENDIF
ENDM
Ниже для примера показано, как осуществляется макроподстановка для макрокоманды
SHIFT А, 5 :
X→A, N→5 IFE 5-1 5-1=0? MOV CL,5
SHIFT A,5 ────────> SHR A,1 ─────> SHR A,CL
ELSE нет
MOV CL,5
SHR A,CL
ENDIF