близости от вершины стека. В переменной хранится, например, состояние
конечного автомата, от которого зависит дальнейшая логика работы
программы. Скажем если там 3, то мы идем делать одно, если 4 то другое,
если 5 то еще что-то и так до 255 состояний. И по логике работы после 3
должна идти 4ре, но никак не 10
И вот было там 3. И тут, в один ужасный момент, условия так совпали, что
стек разросся и его вершина дошла до этой переменной, вписав туда
значение, скажем 20, а потом борзо свалила обратно. Оставив гадость —
классический пример переполнения стека. И логика программы вся
порушилась из-за этого.
Либо обратный пример — стек продавился до переменных, но в этот момент
переменные обновились и перезаписали стековые данные. В результате, со
стека снялось что-то не то (обычно кривые адреса возврата) и программе
сорвало крышу. Вот такой вариант, кстати, куда более безобидный, т.к. в
этом случае ошибка видна сразу и она не всплывает внезапно спустя
неизвестно сколько времени.
Причем эта ошибка может то возникать, то исчезать. В зависимости от того
как работает программа и насколько глубоко она перегружает стек. Впрочем,
такое чаще встречается, когда пишешь на Си, где не видно насколько
активно идет работа со стеком. Для assembler все гораздо прозрачней. И тут
такое может возникнуть из-за откровенно кривого алгоритма.
На долю специалистов по Ассемблеру часто выпадают другие стековые
ошибки. В первую очередь забывчивость. Что-то положил, а достать забыл.
Если дело было в подпрограмме или в прерывании, то искажается адрес
возврата (о нем чуть позже), стек срывает и программа мгновенно рушится.
Либо невнимательность — сохранял данные в одном порядке, а достал в
другом. Раз – и содержимое регистров обменялось.