Указатель стека SP (Stack Pointer)

Понедельник, 27 Фев 2012, 10:38 | Рубрика: Ассемблер

В этой статье о программировании на ассемблере речь пойдет об указателе стека (Stack Pointer, SP). Я постараюсь рассказать простыми словами о том, что такое стек, указатель стека, и для чего он вообще используется в программах на ассемблере.

Стек представляет собой набор ячеек памяти, организованный особым образом. Он служит для записи различных данных, или адресов команд. Физически стек находится внутри микроконтроллера. В микроконтроллерах семейства x51 стек имеет 8 разрядную ячейку памяти (в ней помещается слово из 8 единиц и нулей). Указатель стека – это регистр, который указывает на верхнюю ячейку стека, следующую за последней заполненной ячейкой, куда должны быть записаны новые данные. Все операции со стеком выполняются благодаря указателю стека.

Рассмотрим, в чем заключается особая организация записи данных в стеке. Английский термин stack переводится на русский  в буквальном смысле как «стопка». Представьте себе стопку бумаги. Чтобы взять второй лист, вам нужно сначала снять с вершины первый. Это и есть принцип работы стека, который назван английской аббревиатурой LIFO (Last in first out). Это следует понимать так: «Данные, которые вошли в стек последними, выходят из стека первыми». Операцию помещения данных в стек обычно обозначают Push, изъятия данных из стека – Pop. Данные можно записать только в самую верхнюю ячейку стека, «изъять» данные также можно только из верхней ячейки. Указатель стека показывает, с какой ячейкой стека нужно проводить текущую операцию.

А теперь рассмотрим, зачем вообще нужен  указатель стека, и как это применяется на практике.

Допустим, у нас есть Программа 1 на ассемблере, которая после определенной команды вызывает Программу 2 (подпрограмму). После выполнения Программы 2 управление вновь передается Программе 1, при этом система должна «помнить» все состояния, в которых находилась Программа 1. Как можно узнать, какую команду Программы 1 нужно выполнить после выполнения Программы 2, если известно, что каждой команде программы соответствует свой адрес?

Для того чтобы вернуться в нужное место Программы 1, используется указатель стека (SP). В ячейку стека записывается адрес команды Программы 1 —  адрес того места этой программы, где управление перешло к Программе 2, и куда впоследствии нужно вернуться. После выполнения второй программы, нужный адрес будет изъят из стека при помощи указателя стека, который будет указывать на ячейку стека с нужным адресом. Таким образом, управление вновь будет передано Программе 1, по указанному в стеке адресу. Этот пример проиллюстрирован на рисунке:

Бывают ситуации, когда нужно запомнить не только адрес команды для возврата к ней, но и некие данные, которые были получены в результате работы прерванной программы.  Например, регистр состояния программы PSW. В этом случае, в стек будут записан не только адрес того места, откуда следует возобновить выполнение программы, но и данные (в следующий/ие байт/ы памяти стека).

Ошибки при работе с указателем стека.

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

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

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

В далекие времена существования перфолент, тогдашние программисты умудрялись «соединять» пространство адресов данных и программ, обращаясь поочередно к одним и тем же ячейкам как к командам, и как к данным. Делалось это для того, чтобы экономить длину перфоленты. Сейчас же в этом нет необходимости, так как современной памяти хватает для записи большого числа кода. Подобный способ кодирования использовался также для затруднения деассемблирования програмы (чтобы «воришка» не смог разобраться в коде).

Еще одна возможная ошибка при работе с указателем стека – циклическое заполнение стека одними и теми же данными. В разных микроконтроллерах есть свои особенности реализации данной «возможности» 🙂

Сайт дня:
Хотите рекламировать в интернете медицинские товары и услуги? Нет ничего проще! Реклама на специализированных сайтах и в социальных сетях доступна на сайте internet.reklamy.ru.


Метки записи: , , , , , , , , , , , , , , ,

Ваш отзыв

*