Однокристальные микроконтроллеры семейства MCS-51. Подпрограммы и стек. Память данных. Исследование команд загрузки и извлечения из стека, страница 3

3.1.3. Часто при вызове подпрограмм требуется запомнить содержимое регистров общего назначения, которые использовала основная программа. Затем, при возврате из подпрограммы надо восстановить содержимое этих регистров. Для этой цели удобно использовать стек. Однако следует помнить, что в командах обращения к стеку нужно использовать прямой адрес регистра общего назначения в памяти данных, а не его имя  R0, R1,…,R7. При этом надо учитывать, в каком регистровом банке находятся эти регистры. Например, адрес регистра  R0 в банке 0 будет  00H, адрес этого же регистра в банке 1 будет 08H, а в банке 3 – 18H.

Запишите в память симулятора программу сохранения в стеке содержимого регистров R1, R2, R7  0-го банка:

PUSH  01H  ; Загрузить в стек содержимое регистра R1

PUSH  02H  ; Загрузить в стек содержимое регистра R2

PUSH  07H  ; Загрузить в стек содержимое регистра R7

NOP

Перед выполнением программы занесите в ячейки памяти данных с адресами 01H, 02H и 07H, соответствующие регистрам R1, R2 и R7  0-го банка, произвольные значения, например, 01H, 02H, 07H.

Выполните программу в пошаговом режиме, наблюдая за областью стека и изменением содержимого регистра SP.

Занесите в память симулятора программу восстановления содержимого регистров R1, R2 и R7  0-го банка:

POP  07H  ; Извлечь из стека содержимое регистра R7

POP  02H  ; Извлечь из стека содержимое регистра R2

POP  01H  ; Извлечь из стека содержимое регистра R1

NOP

Перед выполнением программы очистите ячейки памяти данных с адресами 01H, 02H и 07H, соответствующие регистрам R1, R2 и R7  0-го банка.

Выполните программу восстановления содержимого регистров в пошаговом режиме, наблюдая за ячейками памяти данных, соответствующими этим регистрам.

3.2. Исследование команды вызова подпрограммы и возврата из нее

При записи программы на языке Ассемблера для вызова подпрограммы используется команда  с мнемоникой   CALL  label,  где label – это метка, соответствующая первой команде подпрограммы. Обычно имя этой метки соответствует имени (названию) подпрограммы. Возврат из подпрограммы выполняется по команде  RET. Эти команды являются безусловными. 

3.2.1. Создайте в Вашей папке файл с именем count.asm и запишите в него текст программы, которая определяет количество единиц в ячейке памяти данных. Адрес ячейки вводится из порта P1, а результат подсчета выводится в порт P2. Процедура определения количества единиц в байте осуществляется подпрограммой с именем BYTE, алгоритм которой аналогичен программе из п.3.2.3 лабораторной работы № 7. В подпрограмме используется регистр R0 для передачи входного параметра – адреса ячейки памяти данных, из которой берется байт для анализа. Выходной параметр подпрограммы – это регистр R1, в котором находится подсчитанное число единиц.

COUNT: MOV  SP, # 38H  ; Определить стек

MOV  P2, #0        ; Вывести нули в порт P2

MOV  R0, P1       ; Ввод адреса байта из порта P1

CALL  BYTE      ; Вызов подпрограммы подсчета единиц в байте

MOV   P2, R1      ; Вывод количества единиц в порт P2

JMP      $              ; Зацикливание программы

; BYTE - подпрограмма подсчета единиц в байте

; Входной параметр: регистр R0 – адрес байта в ПД

; Выходной параметр: регистр R1 – количество единиц в байте

BYTE:     MOV  R7, #8         ; Загрузить счетчик разрядов байта

MOV  R1, #0          ; Очистить счетчик единиц

MOV  A, @R0       ; Пересылка байта в аккумулятор

CLR   C

SHIFT:    RRC   A                  ; Сдвиг байта вправо через перенос

JNC    MET1          ; Переход, если C=0

INC    R1                ; Инкремент счетчика единиц

MET1:    DJNZ  R7, SHIFT  ; Цикл сдвига, если  (R7) ¹ 0

RET                        ; Возврат из подпрограммы

END                        ; Конец текста программы