Листинг 1-14. Структурированные макросы управления
-----------------------------------------------------------------
PAGE 50,132 ;установить выдачу листинга на полный экран
;;********************************************************
;; М А К Р О О П И С А Н И Я
;;********************************************************
;;
FALSE EQU 0 ;определить "FALSE"
TRUE EQU 0FFFFh ;определить "TRUE"
;;
;;** @TestSym *************************SUPPORT MACRO******
;; Выявить, был ли определен уровень вложенности. Если нет,
;; то установить "?SYMDEF" для инициализации счетчика этого
;; уровня. Обычно все процессы первого прохода запускают
;; счетчик с 0. Значения всех символов в начале прохода 2
;; должны быть сброшены. Заметьте, что символы "?p2sw..."
;; остаются для "Phase 2 SWitch" (переключатели фазы 2).
;; Проверьте, что первым уровнем при реинициализации явля-
;; ется уровень 10. Замечание: значение 10 выбрано для пер-
;; воначального уровня с тем, чтобы зарезервировать для
;; уровня вложенности две цифры.
;;
@TestSym MACRO p1,p2
IF1 ;;если 1-ый проход,проверить что определено
IFNDEF &p1&p2
?p2sw&p1&p2 = TRUE ;;установить для 2-го прохода
;;переопределение переключателей,
?symdef = FALSE ;;вызывающее инициал-ию счетчика
ELSE
?symdef = true ;;разрешить приращение счетчика
ENDIF ;;конец проверки описания символа
ENDIF ;;конец проверки 1-го прохода
;;
IF2 ;;если 2-ой проход, переинициал-ать
IF (?p2sw&p1&p2) ;;если переинициал. нет, то
?p2sw&p1&p2 = FALSE ;;очистить переключатель переопре-
;;деления 2-го прохода
IF (?p2sw&р1&10) ;; и проверить инициал-ию
;;уровня 10
.ERR ;; выйти с сообщением об ошибке
%OUT @TestSym mfcro: &p1 уровень вложенности не
%OUT закрыт на 2-ом проходе
ENDIF ;;закон. уровень 10 по проверке инициал-ции
?symdef = FALSE ;;вызвать переинициал-ию счетчика
ELSE
?symdef = TRUE ;;разрешить приращение счетчика
ENDIF ;;закончить проверку "если не переинициал."
ENDIF ;;закончить проверку прохода 2
ENDM ;;закончить макроописание
;;
;;**@ZeroSym**************************SUPPORT MACRO********
;; Инициализировать счетчик последовательности вложенностей
;; при первом использовании
@ZeroSym MACRO p1,p2
&p1&p2 = 0
ENDM
;;
;; ** @IncSym *********************** SUPPORT MACRO ******
;; Увеличить на 1 счетчик последовательности вложенностей
@IncSym MACRO p1,p2
&p1&p2 = &p1&p2 + 1
ENDM
;;
;; ** @DecSym *********************** SUPPORT MACRO *****
;; Уменьшить на 1 счетчик последовательности вложенностей
@DecSym MACRO p1,p2
&p1&p2 = &p1&p2 -1
ENDM
;;
;; ** @MakeJmp2 ********************** SUPPORT MACRO *****
;; Вставить команду перехода (JMP) в программный код
@MakeJmp2 MACRO p1,p2,p3
jmp &p1&p2&p3
ENDM
;;
;; ** @MakeJmp *********************** SUPPORT MACRO *****
;; Переформатировать символы для команды JMP
@MakeJmp MACRO p1,p2,p3
??tmp = &p3&p2
@MakeJmp2 p1,p2,%??tmp
ENDM
;;
;; ** @MakeJmpLabel2 *****************SUPPORT MMACRO *****
;; Вставить метку команды JMP в программный код
@MakeJmpLabel2 MACRO p1,p2,p3
&p1&p2&p3:
ENDM
;;
;; ** @MakeJmpLabel ****************** SUPPORT MACRO *****
;; Переформатировать символы для определения метки опера-
;; тора JMP
@MakeJmpLabel MACRO p1,p2,p3
??tmp = &p3&p2
@MakeJmpLabel2 p1,pp2,%??tmp
ENDM
;;
;; ** @IfTrue ************ STRUCTURED CONTROL MACRO *****
;; Структурированное макро "IF" - IF TRUE
@IfTrue MACRO p1
LOCAL iftrue
j&p1 iftrue ;;перейти к секции "IF"
IFNDEF ?if_level ;;установить новый уровень
;;вложенности
?if_level = 10
ELSE
?if_level = ?if_level + 1
ENDIF
@TestSym ?if_nest,%?if_level ;;установить новый
;;номер последовательности
If (?symdef)
@IncSym ?if_nest,%?if_level
ELSE
@ZeroSym ?if_nest,%?if_level
ENDIF
;; Вставить переход в секцию "ELSE" или "IF NOT"
@MakeJmp ?if_,%?if_level,?if_nest
iftrue:
ENDM
;;
;; ** @IfElse *********** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "ELSE"
@IfElse MACRO
IFNDEF ?if_level
; ОШИБКА - "@IfElse" без открытого оператора "@IfTrue"
EXITM
ENDIF
IF(?if_level LT 10)
; ОШИБКА - "@IfElse" без открытого оператора "@IfTrue"
EXITM
ENDIF
;; Сгенерировать код "@IfElse"
@IncxSym ?if_nest,%?if_level
@MakeJmp ?if_,%?if_level,?if_nest
@DecSym ?if_nest,%?if_level
@MakeJmpLabel ?if_,%?if_level,?if_nest
@IncSym ?if_nest,%?if_level
ENDM
;;
;; ** @IfEnd *********** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "END" для совместного
;; использования с "@IfTrue"
@IfEnd MACRO
IFNDEF ?if_level
; ОШИБКА - "@IfEnd" без открытого оператора "@IfTrue"
EXITM
ENDIF
IF (?if_level LT 10)
; ОШИБКА - "@IfEnd" без открытого оператора "@IfTrue"
EXITM
ENDIF
;; Сгенерировать метку "@IfEnd"
@MakeJmpLabel ?if_,%?if_level,?if_nest
?if_level = ?if_level - 1
ENDM
;;
;; ** @DoWhile ******** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "DO_WHILE"
@DoWhile MACRO p1,p2,p3
LOCAL iftrue
IFNDEF ?do_level ;;установить новый уровень
;;вложенности
?do_level = 10
ELSE
?do_level = ?do_level + 1
ENDIF
;; Установить номер новой последовательности для уровня
;; вложенности
@TestSym ?do_nest,%?do_level
IF (?symdef)
@IncSym ?do_nest,%?do_level
ELSE
@ZeroSym ?do_nest,%?do_level
ENDIF
;; Вставить метку начала цикла
@MаkeJmpLabel ?do_,%?do_level,?do_nest
;; Вставить в программный код проверку условия
cmp &p1,&p3
;; Перейти к секции "DO_WHILE_TRUE"
j&p2 iftrue
;; Перейти к следующей метке последовательности
@IncSym ?do_nest,%?do_level
;; Вставить в программный код переход на конец цикла
@MakeJmp ?do_,%?do_level,?do_nest
;; Начать секцию "DO_WHILE_TRUE"
iftrue:
ENDM
;;
;; ** @DoExit *********** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "DO_EXIT" для совместного
;; использования с "@DoWhile"
@DoExit MACRO
;; Вставить в программный код переход на конец цикла
@MakeJmp ?do_,%?do_level,?do_nest
ENDM
;;
;; ** @DoEnd ************ STRUCTURED CONTROL MACRO *****
;; Структурированное макро "DO_END" для совместного
;; использования с "@DoWhile"
;; Макро @DoEnd генерирует программный код для структури-
;; рованного ENDDO
@DoEnd MACRO
IFNDEF ?do_level
; ОШИБКА - "@DoEnd" без открытого оператора "@DoWhile"
EXITM
ENDIF
IF (?do_level LT 10)
; ОШИБКА - "@DoEnd" без открытого оператора "@DoWhile"
EXITM
ENDIF
;; Переход на предыдущую метку последовательности
@DecSym ?do_nest,%?do_level
;; Сгенерировать переход на начало цикла
@MakeJmp ?do_,%?do_level,?do_nest
;; Перейти к следующей метке последовательности
@IncSym ?do_nest,%?do_level
;; Сгенерировать метку для "@DoEnd"
@MakeJmpLabel ?do_,%?do_level,?do_nest
?do_level = ?do_level - 1
ENDM
;;
;; ** @Repeat *********** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "@Repeat"
;; "@Repeat" генерирует программный код для структури-
;; рованного REPEAT-UNTIL
@Repeat MACRO
IFNDEF ?rep_level ;;установить новый уровень
;;вложенности
?rep_level = 10
ELSE
?rep_level = ?rep_level + 1
ENDIF
;; Установить новый номер последовательности для уровня
;; вложенности
@TestSym ?rep_nest,%?rep_level
IF (?symdef)
@IncSym ?rep_nest,%?rep_level
ELSE
@ZeroSym ?rep_nest,%?rep_level
ENDIF
;; Вставить метку перехода на начало цикла
@MakeJmpLabel ?rep_,%?rep_level,?rep_nest
ENDM
;;
;; ** @Until ***********STRUCTURED CONTROL MACRO *****
;; Структурированное макро "@Until" для совместного
;; использования с "@Repeat"
@Until MACRO p1,p2,p3
LOCAL iftrue
IFNDEF ?rep_level
; ОШИБКА - "@Until" без открытого оператора "@Repeat"
EXITM
ENDIF
IF (?rep_level LT 10)
; ОШИБКА - "@Until" без открытого оператора "@Repeat"
EXITM
ENDIF
;; Вставить в программный код проверку условия
cmp &p1,&p3
;; Перейти к секции "@Until" .TRUE.
j&p2 iftrue
;; Вставить переход на начало цикла
@MakeJmp ?rep_,%?rep_level,?rep_nest
iftrue:
?rep_level = ?rep_level- 1
ENDM
;;
;; ** @For *********** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "@For". Используйте это
;; макро так:
;; @For counter,begin,end,dir,step
;;
@For MACRO p1,p2,p3,p4,p5
LOCAL first
LOCAL iftrue
IFNDEF ?for_level ;;установить новый
;;уровень вложенности
?for_level = 10
ELSE
?for_level = ?for_level + 1
ENDIF
;; Установить новый номер последовательности для
;; уровня вложенности
@TestSym ?for_nest,%?for_level
IF (?symdef)
@IncSym ?for_nest,%?for_level
ELSE
@ZeroSym ?for_nest,%?for_level
ENDIF
;; Вставить в программный код инициализацию счетчика -
;; (обойти 1-ый шаг)
mov &p1,&p2 ;инициализировать счетчик
jmp first ;начать цикл FOR
;; Вставить метку перехода на начало цикла
@MakeJmpLabel ?for_,%?for_level,?for_nest
;; Вставить в программный код шаг вычислений и выполнить
;; его проверку
IFIDN ,<+>
inc &p1 ;увеличить счетчик
ELSE
IFIDN ,<->
dec &p1 ;уменьшить счетчик
ELSE
; ОШИБКА - неверная спецификация шага в операторе "@For"
EXITM
ENDIF
ENDIF
first: ;проверить на необходимость продолжения
;; Вставить в программный код проверку условия
cmp &p1,&p3 ;достигнут ли конец?
;; Перейти к секции "FOR_TRUE"
IFIDN ,<+>
jl iftrue ;нет - продолжить цикл FOR
ELSE ;;по умолчанию - к шагу "-"
jg iftrue ;нет - продолжить цикл FOR
ENDIF
;; Перейти к следующей метке последовательности
@IncSym ?for_nest,%?for_level
;; Вставить в программный код переход на конец цикла
@MakeJmp ?for,%?for_level,?for_nest
iftrue:
ENDM
;;
;; ** @ForEnd ******** STRUCTURED CONTROL MACRO *****
;; Структурированное макро "FOR_END" для совместного
;; использования с "FOR"
;; @ForEnd генерирует программный код для структури-
;; рованного цикла FOR
@ForEnd MACRO
IFNDEF ?for_level
; ОШИБКА - "@ForEnd" без открытого оператора "FOR"
EXITM
ENDIF
IF (?for_level LT 10) page_end12
;
EXITM
ENDIF
;;
@DecSym ?for_nest,%?for_level
;;
@MakeJmp ?for_,%?for_level,?for_nest
;;
@IncSym ?for_nest,%?for_level
;;
@MakeJmpLabel ?for_,%?for_level,?for_nest
?for_level = ?for_level- 1
ENDM
;; **************************************************
|