Возможность организовывать подпрограммы на языке ассемблера способствует реализации модульного метода программирования. Основная идея этого метода: алгоритм разрабатываемой программы разбивается на отдельные модули, причем каждый модуль реализует единую и независимую функцию. При этом каждый модуль имеет единственную точку входа и единственную точку выхода. Размер модуля стараются минимизировать. Алгоритм основной программы может быть представлен как алгоритм вызова модулей в соответствии с реализуемыми функциями. Модули организуются в виде подпрограмм, при этом необходимо четко следить за входными и выходными параметрами подпрограмм, для того чтобы обеспечить однозначную связь основной программы и подпрограммы. При этом необходимо определить, какие регистры или ячейки содержат входные данные, а какие выходные. Также необходимо следить за тем, куда подпрограмма заносит свои результаты, во избежание потери нужных данных. В частности в подпрограммах часто используют другой банк регистров. Переключение между ними осуществляется при помощи команд SEL RB0 и SEL RB1. По умолчанию выбран банк регистров RB0. Необходимо также следить, чтобы основная программа не попала на подпрограмму при последовательном выполнении команд. Например, подпрограмма располагается после основной программы, а перед ней должна быть команда перехода. Вызов подпрограммы осуществляется командой CALL М, где М – метка или адрес, с которого начинается подпрограмма. Команда занимает два байта и выполняется за два машинных цикла. При этом происходит следующее.
1) (РС) ←(РС)+2
2) ((SP)) ←(PSW 4÷7, PC)
|
|
|
|
|
|
В ячейке стека сохраняются двенадцать разрядов счетчика команд РС с 0 по 11 и 4 разряда регистра PSW c 4 по 7.
3) (SP)←(SP) +1
Указатель стека наращивается на единицу, указывая на следующую ячейку стека, т.к. в вызываемой подпрограмме может оказаться вызов другой подпрограммы, и указанные выше данные сохраняются в следующей ячейке стека. Т.к. ячеек стека восемь, то и уровень вложенности подпрограмм тоже восемь.
4) (PC0÷11) ← код метки или адрес
В счетчик команд PC с 0-го по11-й разряды заносится код метки или адрес, с которого начинается подпрограмма (если быть точным, то (PC0÷10) ← код метки 0÷10), (PC11) ← DBF)).
Возврат из подпрограммы осуществляется с помощью команды RET, занимает 1 байт, но выполняется за два машинных цикла. При этом происходит следующее.
1) (SP)←(SP) – 1
Декремент указателя стека.
2) (PC0÷11)←((SP)0÷11)
В счетчик команд загружается адрес возврата, т.е. адрес следующей за CALL М командой. RET используется для возврата из простых подпрограмм.
RETR – команда возврата из подпрограмм обработки прерываний или для возврата из простых подпрограмм, если требуется сохранить (PSW4÷7), но если при этом прерывания не используется.
1) (SP)←(SP) – 1
2) (PC0÷11) ←((SP)0÷11)
3) (PSW 4÷7) ←((SP)12÷15)
Задания к практическому занятию №5:
программу из лабораторной работы №6 «на бумаге» разместить в ПЗУ микроконтроллера. Задаваясь двумя вариантами исходных данных
(первое число больше или равно второму; второе больше первого), определить по шагам содержимое регистров РС, SP, PSW при каждом вызове подпрограммы и возврате из нее.