Проблема, с которой приходится сталкиваться при многократном использовании участков кодов, — как определить, в какое место памяти программ возвращаться после завершения подпрограммы. Обращение к подпрограмме производится из нескольких мест основной программы.

Описанную ситуацию иллюстрирует рис. 7.2. На нем изображено адресное пространство микроконтроллера. Младшие адреса адресного пространства находятся в нижней части рисунка.

Рис. 7.2.Вызов подпрограммы и возврат к выполнению основной программы

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

Для обращения к подпрограмме и возврата из нее в систему команд микропроцессоров вводят специальные команды. В микроконтроллерах семейства MCS-51 это команды LCALL, ACALL для вызова подпрограммы и команда RET для возврата из подпрограммы. Команды вызова не только осуществляют передачу управления на указанный адрес, но и запоминают адрес команды, следующей за вызовом подпрограммы — адрес возврата. Команда возврата из подпрограммы передает управление по адресу возврата, которой был запомнен при вызове подпрограммы.

Пример вызова подпрограммы и ее реализации на языке программирования ASM-51 приведен на листинге 7.1.

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

В приведенном в листинге 7.1 примере перед подпрограммой обязательно должен быть бесконечный цикл. Иначе в подпрограмму можно попасть не через вызов подпрограммы, а при последовательном выполнении операторов. Тогда команда ret передаст управление на случайный адрес. Это может привести к непредсказуемым последствиям. При особенно неблагоприятных обстоятельствах даже к выходу микропроцессорной системы из строя. В программах, которые пишутся для микроконтроллеров, требуется обеспечить бесконечный цикл для того, чтобы программа никогда не завершала свою работу. Если основная программа микроконтроллера с бесконечным циклом будет располагаться до первой из подпрограмм, то приведенное условие будет выполняться автоматически.

Очень часто возникает необходимость из одной подпрограммы обращаться к другой подпрограмме. Такое обращение к подпрограмме называется вложенным вызовом подпрограммы. Количество вложенных подпрограмм называется уровнем вложенности подпрограмм. Максимально допустимый уровень вложенности подпрограмм определяется количеством ячеек памяти, предназначенных для хранения адресов возврата из подпрограмм.

Стек, его организация и структура

Адреса возврата из подпрограмм хранятся в области памяти, называемой стеком. Логически доступ к этим ячейкам памяти организован так, чтобы считывание последнего записанного адреса возврата производилось первым, а первого — последним. Логическая организация стека пояснена на рис. 7.3. Адресация ячеек стека осуществляется с использованием специального регистра, называемого указателем стека, SP. Ячейка памяти, в которую в данный момент может быть записан адрес возврата из подпрограммы, называется вершиной стека. Ее адрес всегда хранится в указателе стека. Количество ячеек памяти, выделенных для стека, называется глубиной стека. Последняя ячейка стека, в которую можно производить запись, называется дном стека.

Рис. 7.3.Организация стека в памяти данных микропроцессора

Первоначально стек выполнялся аппаратно на отдельных ячейках памяти, затем его стали размещать в обычной памяти данных микропроцессоров. Это позволило в каждом конкретном случае устанавливать необходимую для программы глубину стека. Оставшуюся память можно использовать для размещения глобальных и локальных переменных программы. Глубина стека устанавливается при помощи записи начального адреса вершины стека в регистр SP. Обычно глубина стека устанавливается один раз после включения питания в процедуре инициализации контроллера.

Например, в микроконтроллерах семейства MCS-51 при занесении информации в стек содержимое указателя стека увеличивается (стек растет вверх), поэтому стек размещается в самой верхней части памяти данных.

Для того чтобы установить глубину стека 28 байт, необходимо вычесть из адреса максимальной ячейки внутренней памяти микроконтроллера глубину стека и записать полученное значение в указатель стека SP:

Перейти на страницу:

Поиск

Похожие книги