Код подпрограммы MUL_S приведен в Программе 6.8. В этой программе реализованы этапы 2…4, показанные на Рис. 6.10. Вначале обнуляется переменная MULTIPLICAND_H, используемая для расширения множимого, после чего обнуляются следующие две ячейки фрейма для инициализации произведения. Затем в регистр PSP заносится адрес следующей свободной ячейки, расположенной после фрейма. Таким образом, если из подпрограммы будет вызвана другая подпрограмма, то для следующего уровня вложенности будет задействован свой фрейм, вершина которого будет располагаться сразу же после старого фрейма. В нашем случае эти две команды можно опустить, поскольку вложенные вызовы отсутствуют, правда, при этом потребуется изменить код, реализующий в программе этап 3 в. Именно так и сделано в Примере 6.6 (см. далее).
; Глобальные объявления
PSP equ h’40’; Указатель псевдостека
TOS equ h’50’; Исходная вершина стека
INDF equ 0; Регистр косвенной адресации
FSR equ 04; Индексный регистр
STATUS equ 3; Регистр STATUS
С equ 0; Флаг переноса — бит 0
Z equ 2; Флаг нуля — бит 2
MULTIPLIER equ h’46’; Множитель
MULTIPLICAND equ h’42’; Множимое
MAIN
; Сначала инициализируем вершину стека,
movlw TOS
movwf PSP; адрес которой равен h’40’
;
;Несколько позже, когда необходимо вызвать подпрограмму
; (а)
movf PSP,w; Заносим текущий адрес вершины стека
movwf FSR; в индексный регистр
; (б)
movf MULTIPLIСAND,w;Помещаем множимое в стек,
movf INDF;копируя содержимое регистра
decf FSR, f;и декрементируя FSR
; (в)
movf MULTIPLIER,w; Помещаем множитель в стек,
movwf INDF; копируя содержимое регистра
decf FSR,f; и декрементируя FSR
; (г)
call MUL_S; Вызываем подпрограмму
Основная часть подпрограммы, т. е. реализация 3-го пункта, аналогична Программе 6.7, за исключением того, что для доступа к различным элементам стека необходимо манипулировать содержимым регистра FSR. Единственное место, где использование FSR может быть не очевидным, — реализация этапа 3 в. Поскольку переход к этому блоку может осуществляться различным образом, в зависимости от того, прибавлялось ли множимое к произведению или нет, то содержимое регистра FSR при входе в этот блок не определено. Однако его можно повторно инициализировать значением из регистра PSP, который на данном этапе выполнения программы указывает на регистр, расположенный сразу же после фрейма. Если мы увеличим это значение PSP на 5, то получим адрес параметра MULTIPLICAND.
И в завершение подпрограмма «очищает» стек, записывая в регистр PSP его предыдущее значение. В данном случае для этого оно увеличивается на 5, а в общем случае — прибавляется размер фрейма
Для реализации Программы 6.8 нам потребовалось 45 команд в отличие от 20 команд Программы 6.7. В наихудшем случае на ее выполнение будет затрачено 274 машинных цикла, что также является гораздо худшим результатом по сравнению со 142 циклами Программы 6.7. Таким образом, с какой стороны ни посмотреть, такая стековая модель явно хуже, если не принимать во внимание возможность повторного использования кода и его надежность. Использование стековой модели будет более оправданно в случае написания больших программ при ограниченных ресурсах памяти. Однако программы, выполняющиеся на микроконтроллерах PIC младшего и среднего уровней, как правило, не очень сложны. Более того, маленький объем памяти программ может наложить дополнительные ограничения на использование такого довольно экстравагантного решения. Если время выполнения программы критично, то дополнительные накладные расходы на поддержание стека не стоят полученных результатов.