Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабы / Lab_moto / 4.doc
Скачиваний:
17
Добавлен:
16.04.2013
Размер:
191.49 Кб
Скачать

2. Программное прерывание swi.

Как было отмечено выше, SWI является программным прерыванием и инициируется программистом, в отличие от других прерываний, генерируемых аппаратурой микроконтроллера. SWI является немаскируемым, то есть его нельзя программно запретить.

Для генерации этого прерывания используется команда ассемблера SWI, при выполнении которой происходит следующее:

1. инкрементируется счетчик команд PC, в стеке сохраняется сначала младший, затем старший байты PC;

2. в стеке последовательно сохраняются регистры X, A, C;

3. в счетчик команд заносятся два байта, хранящихся по адресам $1FFC, $1FFD;

Таким образом, после выполнения команды SWI указатель стека смещается на пять байт в сторону младших адресов, и управление передается по вектору, записанному в ячейках $1FFC, $1FFD.

В качестве примера использования команды SWI рассмотрим программу вычисления факториала.

Программу организуем следующим образом:

· с адреса $200 запишем блок начальной инициализации ячеек памяти и вызова подпрограммы обработки прерывания;

· с адреса $300 будет находиться собственно подпрограмма обработки прерывания, вычисляющая факториал;

· по адресу $400 поместим вспомогательную подпрограмму умножения двух чисел.

В ячейке $50 разместим аргумент, а в ячейку $51 будем записывать результат (то есть факториал от содержимого ячейки $50).

Рассмотрим программу вычисления 4!

Основной блок :

200 LDA #$4 Записываем аргумент

202 STA $50 в ячейку $50.

204 LDA #$1 Записываем 1

206 STA $51 в ячейку $51.

208 RSP Устанавливаем указатель стека в $FF.

209 SWI Генерируем вызов подпрограммы обработки прерывания.

20А LDA $51 Записываем результат вычислений в регистр А.

20С BRA 20С Организуем бесконечный цикл.

Подпрограмма обработки прерывания :

300 LDA $50 Сравниваем аргумент

302 CMP #$1 с единицей.

304 BEQ $30С Если аргумент равен единице, то переходим на $30С (вычисления окончены),

306 JSR $400 иначе вызываем подпрограмму умножения чисел.

309 DEC $50 Уменьшаем аргумент на единицу.

30В SWI Вызываем подпрограмму вычисления факториала.

30С RTI Возврат из подпрограммы.

Подпрограмма умножения двух чисел :

400 LDA $50 Перемножаем два числа,

402 LDX $51 находящихся в ячейках

404 MUL $50 и $51.

405 STA $51 Запоминаем результат.

407 RTS Возврат из подпрограммы.

Следующие несколько замечаний поясняют работу программы:

· при выполнении команды SWI, расположенной по адресу $209, в стеке сохраняются значения регистров PC, X, A, C, указатель стека SP смещается на 5 байт вниз, то есть в сторону младших адресов, и управление передается по адресу, записанному в ячейках $1FFC (старший байт) и $1FFD (младший байт), где находится вектор программного прерывания (в нашем случае - $300);

· поскольку мы вычисляем факториал, используя рекурсию, то подпрограмма обработки прерывания будет иметь следующую структуру:

1. проверка условия завершения вычислений, возврат из подпрограммы в случае его истинности;

2. уменьшение аргумента на единицу и вложенный вызов этой же подпрограммы;

· при выполнении команды SWI, расположенной по адресу $30В, происходит вызов подпрограммы вычисления факториала от числа, на единицу меньшего, чем то, что хранится в ячейке $50; при этом регистры опять сохраняются в стеке, указатель стека смещается на 5 байт в сторону младших адресов, и управление передается по адресу, хранящемуся в ячейках $1FFC, $1FFD;

· задача вспомогательной подпрограммы умножения чисел - перемножить два числа, хранящихся в ячейках $50, $51 и поместить младший байт результата в ячейку $51;

Для правильной работы программы необходимо занести адрес подпрограммы обработки прерывания в ячейки $1FFC, $1FFD ($03 в $1FFC и $00 в $1FFD) и поставить точку останова по адресу $20C.

Запустите программу с адреса $200. На экране появится содержимое регистров микроконтроллера, причем регистр A будет содержать результат работы нашей программы: число $18 (в десятичной системе счисления оно равно 24). Можно убедиться, что в ячейке $51 находится то же самое.

Выведите на экран дамп памяти с $C0 по $FF ячейки. Эту область занимает стек. Напомним, что стек начинается с ячейки $FF и по мере заполнения растет вниз - в сторону младших адресов. Начиная с адреса $FF и ниже расположены 30 байт, которые использовала наша программа в процессе работы. Каждый раз при выполнении команды SWI занимаются очередные свободные пять ячеек памяти в стеке, а при выполнении команды RTI из последних пяти использованных ячеек считываются значения регистров, и указатель стека увеличивется на 5 байт, то есть занятая часть стека становится короче. После завершения работы программы стек полностью освобождается, указатель стека принимает то значение, которое он имел до запуска программы, но вся информация, сохраненная в свое время в стеке, остается. Убедитесь в этом.

Тем не менее, при написании и отладке программ следует иметь ввиду, что стек может занимать максимум 64 байта (адреса $C0...$FF). Если происходит переполнение, то указатель стека циклически смещается на начало , что приводит к потере данных. Из вышесказанного следует, что для нашего примера максимальное значение аргумента равно 10, в этом случае стек заполнится целиком. Однако, поскольку мы отвели под результат лишь один байт, то программа перестанет правильно работать уже при значении аргумента, равном 6. Избежать этого можно, предусмотрев в подпрограмме умножения чисел сохранение двухбайтного результата.

Соседние файлы в папке Lab_moto