Выбрать главу

Далее программа очищает массивы DATA и NORM, инициализирует некоторые регистры (адресов и данных) и сбрасывает флаг останова. Последний шаг заключается в изменении содержимого вектора INT5 (который пока указывает на метку idle__int в обработчике прерываний) на адрес wait__trig или sweep__start в зависимости от того, какой режим установлен на управляющей панели: внешнего запуска или автозапуска.

Наконец, главная программа входит в «рабочий» цикл, в котором многократно выполняются два действия: вызов подпрограммы update (обновления массива DISPLAY в соответствии с содержимым массива DATA) и проверка флага останова stop__flag. На фоне этого унылого цикла прерывания тайком выполняют все то, ради чего был сделан наш прибор.

Главная программа: подпрограммы. Перед тем как взяться за наиболее сложную программу нашего комплекса - обработчик прерываний, рассмотрим две подпрограммы, вызываемые главной программой (рис. 11.20).

Рис. 11.20. Структурные схемы подпрограмм.

Подпрограмма clear__arrays заполняет нулями оба массива DATA и NORM; массив DISPLAY очищать нет необходимости, потому что программа update сразу же скопирует нули из DATA в DISPLAY. Эта программа обновляет за раз одно значение из массива DISPLAY, используя для этого текущие параметры изображения с управляющей панели и входные данные из массивов DATA и NORM; она также обновляет состояние порта ЭЛД, копируя байт памяти led__store.

Рассмотрим сначала простую подпрограмму clear__arrays из программы 11.3. Регистры А0 и А1 используются, как указатели двух массивов, и все 32 разряда D0 заполняются нулями. Счетчик D1 инициализируется величиной, равной размеру массива минус один; сейчас станет понятно, зачем это нужно. В цикле слово или длинное слово нулей пересылается в массивы с помощью косвенной адресации (с постинкрементом); вспомните, что постинкрементная адресация — штука интеллигентная, она инкрементирует адресный регистр правильным образом, прибавляя в нашем случае 2 в операции со словом и 4 в операции с длинным словом. Команда DBF заслуживает особого объяснения. Она представляет собой один из вариантов команды DBcc, для которого код условия ее = «ложь» (False). Любая команда (в общем виде) DBcc Dn, метка фактически проверяет два условия.

Сначала она анализирует выполнение условия ее (т. е. состояние флагов, установленное предыдущей командой), при этом, если ее = «истина», ничего не делается (т. е. команда как бы пропускается и ЦП переходит к выполнению следующей команды). Если, однако, ее = «ложь», происходит декремент указанного регистра (как слова) и переход на метку метка, с предварительным анализом содержимого регистра. Если в регистре обнаруживается — 1, переход на метку не осуществляется, и выполняется следующая команда. В нашем случае команда DBcc действует просто как оператор цикла, так как ее = F («всегда ложь», см. табл. 11.1), поэтому декремент D1 осуществляется безусловно, до тех пор, пока не обнаружится D1 = — 1. Несмотря на эти сложности (а также и необходимость использовать счетчик длиной в слово), команда DBcc весьма удобна, так как заменяет две команды (SUBQ, Вcс), и выполняется очень быстро. Поскольку она проверяет счетчик на —1, последний следует инициализировать числом, на 1 меньшим требуемого числа шагов, чем и объясняется инициализация, использованная в программе. Подпрограмма заканчивается обычной командой RTS (возврат из подпрограммы), восстанавливающей исходное содержимое PC (программного счетчика) и осуществляющей таким образом возврат в вызывающую программу.

Заметьте, что в начале подпрограммы не понадобилось сохранять содержимое каких-либо регистров, потому что вызывающая программа не оставила ничего ценного в регистрах D0-D1 и А0-А1. Обратите также внимание на использование MOVE, а не CLR для обнуления массивов; оказывается, команда MOVE работает быстрее CLR из-за особенностей архитектуры МП 68000 — при выполнении CLR МП 68000 сначала инициализирует цикл чтения, а затем — цикл записи. Разработчики приняли такое, на первый взгляд, странное решение для упрощения логики ЦП.

Упражнение 11.13. Напишите вариант подпрограммы clear arrays с использованием команд SUBQ и Всс вместо DBF. Напишите еще один вариант, в котором вместо MOVE используется CLR.