Почему стеки обычно растут вниз? - PullRequest
85 голосов
/ 10 января 2010

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

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

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

Ответы [ 9 ]

43 голосов
/ 10 января 2010

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

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

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

Что касается роста стеков, не все они растут вниз, подробности см. в этом ответе .

20 голосов
/ 10 января 2010

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

6 голосов
/ 10 января 2010

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

4 голосов
/ 10 января 2010

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

3 голосов
/ 27 января 2019

Стэнли Мазор (архитектор 4004 и 8080) объясняет, как было выбрано направление роста стека для 8080 (и в конечном итоге для 8086) в "Микропроцессорах Intel: от 8008 до 8086" :

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

2 голосов
/ 10 января 2010

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

1 голос
/ 21 февраля 2018

Просто на 2с больше:

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

Лично я считаю это недостатком дизайна безопасности. Если, скажем, разработчики архитектуры x64 изменили бы направление роста стека, большинство переполнений буфера стека были бы устранены - что является большой проблемой. (так как струны растут вверх).

1 голос
/ 23 сентября 2011

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

0 голосов
/ 10 января 2010

Я не уверен, но я занимался программированием для VAX / VMS в те дни. Кажется, я помню, как одна часть памяти (куча ??) росла, а стек снижался. Когда они встретились, у вас не было памяти.

...