Почему стеки обычно растут вниз?

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

Мне интересно историческое обоснование этого. Я знаю, что в едином адресном пространстве удобно запускать стек на противоположном конце сегмента данных (скажем), поэтому проблема возникает только в том случае, если две стороны сталкиваются посередине. Но почему стек традиционно получает верхнюю часть? Особенно учитывая, насколько это противоположно "концептуальной" модели?

(и обратите внимание, что в архитектуре 6502 стек также растет вниз, хотя он ограничен одной 256-байтовой страницей, и этот выбор направления кажется произвольным.)

6 ответов


что касается исторического обоснования, я не могу сказать наверняка (потому что я их не проектировал). Мой мысли дело в том, что ранние процессоры получили свой исходный счетчик программ равным 0, и это было естественное желание запустить стек на другом конце и расти вниз, так как их код естественно растет вверх.

в стороне, обратите внимание, что эта настройка счетчика программы на 0 при сбросе не относится к все ранние процессоры. Например, Motorola 6809 будет получать счетчик программ из адресов 0xfffe/f таким образом, вы можете начать работать в произвольном месте, в зависимости от того, что было предоставлено по этому адресу (обычно, но ни в коем случае не ограничиваясь, ROM).

одной из первых вещей, которые сделали бы некоторые исторические системы, было бы сканирование памяти сверху, пока она не найдет место, которое будет считывать то же самое значение, записанное, чтобы она знала фактическую установленную ОЗУ (например, Z80 с адресным пространством 64K не обязательно иметь 64K или RAM, на самом деле 64K было бы огромные в мои первые дни). Как только он найдет верхний фактический адрес, он установит указатель стека соответствующим образом и может начать вызывать подпрограммы. Это сканирование обычно выполняется процессором, выполняющим код в ПЗУ в рамках запуска.

что касается роста стеков, не все из них растут вниз, см. ответ для сведения.


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


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


IIRC стек растет вниз, потому что куча растет вверх. Все могло быть наоборот.


Я считаю, что это чисто дизайнерское решение. Не все они растут вниз-смотри!--1-->это так нити для хорошего обсуждения направления роста стека на разных архитектурах.


Я считаю, что Конвенция началась с IBM 704 и его печально известного "регистра декремента". Современная речь назвала бы это смещением поля инструкции, но дело в том, что они пошли вниз, не до.