|
|
|
|
Защита целостности данных
Другой областью, восприимчивой к разрушению, является стек. В связи с тем, что стек смешивает коды и данные, ошибка в стеке непременно явится
результатом ошибки в программе при попытке процессора использовать данные как ссылку на инструкцию.
Два наиболее общих случая разрушения стека вызывают проблемы ошибочного выравнивания. Первый случай - из-за несоответствия операций PUSH и POP,
а второй - благодаря попытке извлечь данные с помощью инструкции POP, которые были помещены по другую сторону инструкций CALL или RET. Эти проблемы
можно избежать только путем удаления особого внимания "спариванию" инструкций PUSH и POP, используемых в программе, и обеспечения гарантии в том, что
такие пары не выполняют ссылки за границы подпрограммы.
В случае передачи параметров возникает вопрос, а как подпрограмма выполняет очистку стека? Обычно, правило для такого случая состоит в том, что
программа, передавшая в стек данные по инструкции PUSH, получает данные из стека по инструкции POP. Если следовать этому правилу, то путем чтения
листинга одной, а не двух подпрограмм программист может проверить, что стек выровнен. Однако, жесткое следование этому правилу предотвращает использование
для очистки стека инструкций микропроцессора 8086 RET N. Если интерфейс между двумя программами полностью отлажен и надежен, то приемлемый риск
состоит в использовании инструкции RET N.
Всякий раз, когда программа должна быть закодирована для приема переменного количества параметров, не следует использовать инструкцию RET N. Имеются
различные пути ограничения глобальной возможности очистки стека только для установленного количества переменных, но все, вызываемые ими трюковые
манипуляции со стеком, являются затруднительными для понимания и более трудными в отладке. Если подпрограмма должна принимать переменное количество
параметров, то очищать эти параметры из стека должна вызывающая подпрограмма. Кроме того, вызывающая подпрограмма должна ясно указывать вызываемой
программе количество передаваемых для нее параметров.
Все операции, выполняемые над стеком, за исключением операций PUSH и POP, должны происходить под флагом указателя стека и для доступа к стеку
использовать регистр BP. Это значит, что указатель стека должен быть установлен в значение ниже манипулируемого элемента. Если манипулируемые данные
остаются неизменными, то возникает прерывание. По этой же причине нельзя непосредственно манипулировать указателем стека до тех пор, пока не
произойдет переключение стека, или открытие памяти стека. Если произойдет прерывание в то время, когда указатель стека не указывает истинную вершину
стека, то данные в стеке могут быть потеряны. Все сказанное выше не является предостережением для умелого использования манипуляции стеком.
|
|