В информатике, компьютерной инженерии и реализация языков программирования, стековая машина - это режим вычислений, в котором исполнительное управление полностью поддерживается путем добавления (выталкивания), чтения и усечения (выталкивания) в порядке (FILO, также последний пришел - первый вышел или LIFO) буфер памяти, известный как стек, требующий очень мало регистров процессора. Определить конкретную программу может, например, Burroughs B5000, например, интерпретатор для Adobe 's PostScript язык форматирования. печати, или может только приветствовать в части потока выполнения программы.
Описание такого метода, требующего одновременного хранения в регистрах только двух значений, с ограниченным набором предопределенных операндов, которые можно было расширить путем определения дополнительных операндов, функций и подпрограмм, было впервые представил на конференции Роберт С. Бартон в 1961 году.
Это контрастировало с типичным потоком программы, которое могло прыгать туда-сюда, казалось бы, случайным образом, все еще часто встречающийся сегодня, когда обычно много значений, хранящиеся в регистрах, резерв места в памяти для управления потоком программы, где также можно использовать стек, но не строго придерживается в качестве единственного средства управления.
В стековой машине операнды, используемое в инструкциях, всегда имеют известное смещение (заданное в указателе стека) от фиксированного местоположения (нижняя часть стека, которая в конструкции оборудования всегда может быть в нулевой ячейке памяти), экономя драгоценную память в - cache или in- CPU от использования для хранения стольких адресной памяти или номеров индексов. Это приводит к стилю набора команд (ISA), известному как формат нулевого адреса, и может быть такими регистры и кэш для использования в непоточных вычислениях.
Использование Интернета как программным обеспечением, даже если используемое программное обеспечение не является строго стеклом, аппаратный стек может более имитировать внутреннюю работу своих точно программ. Регистры процессора имеют высокие тепловые затраты, и стековая машина может требовать более высокой энергоэффективности. Однако эти разработки обычно уступают традиционным системам регистровой машины и остаются нишевым игроком на рынке.
Java язык программирования виртуальная машина, ядро ОС Android, используемой на смартфонах, является очень часто встречающимся примером стековой машины.
«Стековая машина» - это компьютер, который использует стек «последний вошел, первый вышел» для удержания коротких позиций. жил временно помещения. Большинство его инструкций предполагают, что операнды будут из стека, а результаты будут помещены в стек.
Для типичной инструкции, такой как , компьютер берет оба операнда из самых верхних (самых последних) значений стека. Компьютер заменяет эти два значения суммой, которую компьютер вычисляет при выполнении инструкции
сложить
. Операнды инструкции «выталкиваются» из стека, а ее результат (-ы) затем «помещаются» обратно в стек, готовые для следующей инструкции. Большинство инструкций стека имеют только код операции , управляющий операцией, без дополнительных полей для идентификации константы, регистра или ячейки памяти. Стек легко содержит более двух входов или более одного результата, поэтому можно вычислить более богатый набор операций. Целочисленные операнды-константы часто передаются инструкциями Немедленная нагрузка
. К памяти часто обращаются инструкции Загрузить
или Магазин
, содержащие адрес памяти или вычисляющие адрес из значений в стеке.
Для повышения скорости стековая машина часто реализует часть своего стека с регистрами. Для быстрого выполнения операнды арифметико-логического блока (ALU) могут быть двумя верхними регистрами стека, а результат ALU сохраняется в верхнем регистре стека. Некоторые стековые машины имеют стек ограниченного размера, реализованный как регистровый файл. ALU получит доступ к индексу. Некоторые машины имеют неограниченный размер, реализованный в виде массива в ОЗУ, доступ к которому осуществляется адресным регистром «вершины стека». Это медленнее, но количество триггеров меньше, что делает ЦП менее дорогим и компактным. Его самые верхние значения могут быть кэшированы для скорости. Некоторые машины имеют как стек выражений в памяти, так и отдельный стекров. В этом случае программное обеспечение или прерывание перемещать данные между ними.
Набор инструкций выполняет все действия ALU с постфиксными (обратная польская нотация ), которые работают только со стеком выражений, а не с регистрами данных или ячейками основной памяти. Это может быть очень удобно для исполнения на языках высокого уровня, потому что большинство арифметических выражений можно легко перевести в постфиксную нотацию.
Нап, регистровые машины хранят временные значения в небольшом быстром массиве регистров. Накопительные машины имеют только один регистр общего назначения. Ленточные машины используют очередь FIFO для хранения временных значений. Машины с преобразованием памяти в память не имеют регистровых временных интервалов, которые могут использовать программист.
Стековые машины имеют свои стек выражений и свои стекловыделения-возврата разделенными или как одну интегрированную структуру. Инструкции стековой машины могут быть конвейерными с меньшим взаимодействием и меньшей сложностью проектирования. Обычно он может работать быстрее.
Некоторые портативные технические калькуляторы используют обратную польскую нотацию в интерфейсе клавиатуры вместо клавиш-скобок. Это разновидность стековой машины. Клавиша Plus полагается на то, что два ее операнда уже находятся в правильных верхних позициях видимого пользователя стека.
В коде стековой машины наиболее частые инструкции состоят только из кода операции, выбирающего операцию. Это может легко поместиться в 6 бит или меньше. Инструкции для кратковременного запуска аргумента, но стековые машины организуют так, чтобы частые случаи этого по-прежнему умещались вместе с кодом операции в компактную группу битов. Выбор операндов из предыдущих результатов осуществляется неявно путем упорядочивания инструкций. В отличие от этого, регистровым машинам для выбора операндов требуется два или три поля номеров регистров на команду ALU; машины с самым плотным регистром в среднем составляют около 16 бит на инструкции.
Инструкции для накопительных машин или машин с памятью в память не дополняются полями регистров. Вместо этого они используют анонимные переменные, управляемые компилятором для значений подвыражения. Эти временные ячейки требуют инструкций по обращению к памяти, которые занимают больше места для кода, чем для стековой машины или даже для компактных регистровых машин.
Все практические стековые машины имеют варианты загрузки операций для доступа к локальным переменным и формальными параметрами без явных вычислений адреса. Это может быть смещение от текущего местоположения вершины стека или смещение от стабильного регистра базы данных. Регистровые машины обрабатывают это в режиме адреса «регистр + смещение», но используют более широкое поле смещения.
Плотный машинный код был очень ценен в 1960-х, когда основная память была очень и очень ограничена даже на мэйнфреймах. Это снова стало важным крошечным воспоминаниям о мини-компьютерах, а затем о микропроцессорах. Плотность используется сегодня для приложений для смартфонов, приложений, загружаемых в браузеры через медленное Интернет-соединение, а также в ПЗУ для встроенных приложений. Более общим улучшением инструкций по увеличению плотности кеширования и предварительной выборки.
Некоторая плотность кода Burroughs B6700 была связана с перемещением информации об операнде в другое место, в «теги» в каждом слове данных или в таблицах указателей. Сама инструкция Добавить была универсальной или полиморфной. Он должен был получить операнд, чтобы определить, было ли это добавлением целого числа или сложения с плавающей запятой. Команда запускала себя срабатыванием непрямого адреса или, что еще хуже, замаскированного вызова подпрограммы call-by-name thunk. Общие коды операций требуют меньшего количества битов кода операций.
Компиляторы для стековых машин проще и быстрее строить, чем компиляторы для других машин. Генерация кода тривиальна и не зависит от предыдущего или последующего кода. На рисунке показано синтаксическое дерево, соответствующий пример выражения A * (B-C) + (D + E).
Дерево двоичного синтаксиса для выражения A * (BC) + (D + E)Скомпилированный код для простой стековой машины примет форму (соответствующей обратной польской нотации выражений ABC - * DE + +):
# содержимое стека (крайний левый = верхний): нажмите A # A нажмите B # BA нажмите C # CBA вычесть # BC A умножить # A * (BC) нажать D # DA * (BC) нажать E # EDA * (BC) добавить # D + EA * (BC) add # A * (BC) + (D + E)
Действуют арифметические операции «вычитание», «умножение» и «сложение» на двух самых верхних операндах стека.
Такую простую компиляцию можно выполнить с помощью прохода синтаксического анализа. Управление реестром не требуется. Большинство стековых машин могут копировать записи стека, чтобы избежать доступа к памяти (что намного медленнее), но обычно это тривиально. Тот же код операции, обрабатывает частый общий случай добавления, индекс или запускает функции вызова, также будет обрабатывать общий вызов, включающий сложный подвыражения и вложенные вызовы. Компилятору и процессору не нужны особые случаи для инструкций, которые имеют отдельные пути вычисления адресов.
Эта простота позволяла компиляторам уместиться на очень маленьких машинах. Простые компиляторы позволили новым линейкам продуктов быстро выйти на рынок и позволили новым операционным системам быть написанными полностью на языке высокого уровня, а не на ассемблере. Например, UCSD p-System поддерживающая полную среду программирования учащихся на ранних 8-битных микропроцессорах с плохим набором команд и небольшим объемом оперативной компиляции в виртуальную стековую машину, а не на фактическую машину.
Обратной стороной простоты компиляторов для стековых машин является то, что чистые стековые машины имеют меньше оптимизаций (см. Подразделы в § недостатки производительности стековых машин). Однако оптимизация скомпилированного кода стека вполне возможна. Внутренняя оптимизация оптимизатора самого компилятора улучшает работу самого инструмента.
Некоторые наборы команд стековой машины предназначены для интерпретирующего выполнения представленных машин, а не для прямого управления оборудованием. Интерпретаторы для машин с виртуальным стеком легче построить, чем интерпретаторы для машин регистров или машин с памятью в память; логика для обработки адресации памяти находится только в одном месте, а не повторяется во многих инструкциях. Стековые машины также имеют меньше вариантов кода операции; один обобщенный код операции будет обрабатывать как частые, так и неясные угловые ошибки на память или настройку вызова функций. (Норма кода часто повышается путем добавления коротких и длинных форм для одной и той же операции.)
Времен нет полей операндов для декодирования, стековые машины выбирают каждую инструкцию и ее операнды одновременно. Стековые машины могут пропускать этап выборки операндов регистровой машины. Кроме того, за исключением явной загрузки из памяти инструкций, порядок использования операндов идентичен порядку операндов в стеке данных. Превосходная предварительная выборка легко достигается за счет хранения операндов наверху стека в быстром хранилище. Например, в микропроцессоре Java Optimized Processor (JOP) два верхних операнда напрямую входят в схему пересылки данных, которая работает быстрее, чем регистровый файл.
Быстрый доступ также полезен для переводчиков. Большинство интерпретаторов регистров указывают свои регистры по номерам. Но доступ к регистрам хост-машины в индексированном массиве невозможен, поэтому для виртуальных регистров выделяется массив памяти. Следовательно, инструкции интерпретатора регистров должны использовать память для передачи сгенерированных данных следующей инструкции. Это вынуждает интерпретаторы регистров работать намного медленнее на микропроцессорах, сделанных с точным правилом обработки (т.е. более быстрые транзисторы без повышения скорости схемы, такие как Haswell x86). Для этого требуется несколько часов для доступа к памяти, но только одни часы для доступа к регистру. В случае стековой машины со схемой пересылки данных вместо регистров интерпретаторов стека могут выделять регистры хост-машины для нескольких верхних операндов стека вместо памяти хост-машины.
Машина со стеком выражений может обойтись всего двумя регистрами, видимыми программистами: адрес вершины стека и адрес следующей инструкции. В минимальной аппаратной реализации гораздо меньше битов триггеров или регистров. Более быстрые разработки могут просто буферизовать N самых верхних ячеек стека в регистры, чтобы сократить циклы стека памяти.
Ответ на прерывание включает сохранение регистров в стеке, а затем переход к коду обработчика прерывания. В стековой машине большинство параметров уже находится в стеке. Следовательно, нет необходимости их туда толкать. Часто стековые машины быстрее реагируют на прерывания. Некоторые регистровые машины справляются с этим за счет нескольких файлов, которые можно мгновенно менять местами, но это увеличивает затраты и замедляет регистрацию файла.
Некоторые считают, что стековые машины выполняют больше циклов кеширования данных для временных значений и локальных
На машинах со стеком временные значения часто попадают в память, тогда как на машинех с большим количеством регистров эти временные значения обычно остаются в регистрах. (Однако эти значения часто необходимо разделить на «кадры активации» в конце определения процедур, базового блока или по крайней мере, в буфер памяти во время обработки прерывания). Значения, перенесенные в память, увеличивают количество циклов кеширования. Этот эффект пролива зависит от количества скрытых регистров, используемых для буферизации вершины стека, от циклических вложенных процедур и от скорости обработки прерываний главного компьютера.
Некоторые простые стековые машины или интерпретаторы стека используют аппаратные регистры верхнего уровня. Эти минимальные реализации всегда медленнее, чем стандартные регистровые машины. Типичное выражение, такое как X + 1
, компилируется в Load X
; Загрузка 1
; Добавить
. При этом выполняется неявная запись и чтение стека памяти, которые не были необходимы:
, всего 5 ссылок на кэш данных.
Следующий шаг - стековая машина или интерпретатор с одним регистром вершины стека. Затем приведенный выше код выполняет:
, всего 5 ссылок на кэш данных, в худшем случае. Обычно интерпретаторы не отслеживают пустоту, потому что им это не нужно - все, что находится ниже указателя стека, является непустым значением, а регистр кэша TOS всегда остается активным. Однако типичные интерпретаторы Java не буферизуют верхнюю часть стека таким образом, потому что программа и стек имеют сочетание коротких и широких значений данных.
Если аппаратная стековая машина имеет N регистров для кэширования самых верхних слов стека памяти, то в этом примере исключаются все выбросы и пополнения, и имеется только 1 цикл кэширования данных, такой же, как для регистровой или аккумуляторной машины..
На регистровых машинах, использующих оптимизирующие компиляторы, часто наиболее часто используемые локальные переменные остаются в регистрах, а не в ячейках памяти кадра стека. Это устраняет большинство циклов кеширования данных для чтения и записи этих значений. Разработка «планирования стека» для выполнения анализа динамических переменных и, таким образом, сохранения ключевых переменных в стеке в течение длительных периодов времени, помогает решить эту проблему.
С другой стороны, регистровые машины должны передавать многие из своих регистров в память через вызовы вложенных процедур. Решение о том, какие регистры и когда передавать, принимается статически во время компиляции, а не на основе динамической глубины вызовов. Это может привести к увеличению трафика кэша данных, чем в расширенной реализации стековой машины.
В регистровых машинах общее подвыражение (подвыражение, которое используется несколько раз с одним и тем же значением результата) может быть просто вычислено один раз и его результат сохраняется в быстром регистре. Последующее повторное использование не требует затрат времени или кода, только ссылка на регистр. Эта оптимизация ускоряет простые выражения (например, загрузку переменной X или указателя P), а также менее распространенные сложные выражения.
Напротив, в стековых машинах результаты могут быть сохранены одним из двух способов. Во-первых, результаты можно сохранить с помощью временной переменной в памяти. Хранение и последующее извлечение требуют дополнительных инструкций и дополнительных циклов кеширования данных. Это является преимуществом только в том случае, если вычисление подвыражения требует больше времени, чем выборка из памяти, что почти всегда имеет место в большинстве стековых процессоров. Это никогда не имеет смысла для простых переменных и выборок указателей, потому что они уже имеют одинаковую стоимость одного цикла кеширования данных за доступ. Это имеет лишь незначительную ценность для таких выражений, как X + 1
. Эти более простые выражения составляют большинство избыточных, оптимизируемых выражений в программах, написанных на неконкатенативных языках. Оптимизирующий компилятор может выиграть только за счет избыточности, которой программист мог бы избежать в исходном коде.
Второй способ оставляет вычисленное значение в стеке данных, дублируя его по мере необходимости. При этом используются операции для копирования записей стека. Стек должен иметь достаточно мелкую глубину для доступных инструкций копирования ЦП. Рукописный стековый код часто использует этот подход и достигает скорости, как у регистровых машин общего назначения. К сожалению, алгоритмы оптимального «планирования стека» не широко используются языками программирования.
В современных машинах время выборки переменной из кэша данных часто в несколько раз больше, чем время, необходимое для базовых операций ALU. Программа работает быстрее без остановок, если загрузка ее памяти может быть запущена за несколько циклов до инструкции, которая нуждается в этой переменной. Сложные машины могут делать это с помощью глубокого конвейера и «выполнения вне очереди», которые проверяют и выполняют множество инструкций одновременно. Регистрирующие машины могут делать это даже с помощью гораздо более простого «упорядоченного» оборудования, неглубокого конвейера и немного более умных компиляторов. Шаг загрузки становится отдельной инструкцией, и эта инструкция статически планируется намного раньше в кодовой последовательности. Компилятор помещает между ними независимые шаги.
Для планирования доступа к памяти требуются явные резервные регистры. Это невозможно на стековых машинах без раскрытия программисту некоторых аспектов микроархитектуры. Для выражения A-B правый операнд должен быть вычислен и передан непосредственно перед шагом минус. Без перестановки стека или аппаратной многопоточности относительно небольшой полезный код может быть вставлен между ними, ожидая завершения загрузки B. Стековые машины могут обойти задержку памяти, либо имея глубокий конвейер выполнения вне очереди, охватывающий сразу несколько инструкций, либо, что более вероятно, они могут переставлять стек, чтобы они могли работать с другими рабочими нагрузками, пока загрузка завершается, либо они может чередовать выполнение различных программных потоков, как в системе Unisys A9. Однако сегодняшние все более параллельные вычислительные нагрузки предполагают, однако, что это не может быть недостатком, который, как считалось, был в прошлом.
Алгоритм Томасуло находит параллелизм на уровне инструкций, выпуская инструкции по мере того, как их данные становятся доступными. По сути, адреса позиций в стеке ничем не отличаются от регистровых индексов регистрового файла. Это представление позволяет использовать выполнение вне очереди алгоритма Томасуло со стековыми машинами.
Выполнение вне очереди в стековых машинах, кажется, уменьшает или устраняет многие теоретические и практические трудности. Процитированное исследование показывает, что такая стековая машина может использовать параллелизм на уровне команд, и полученное оборудование должно кэшировать данные для инструкций. Такие машины эффективно обходят большинство обращений к стеку памяти. В результате достигается производительность (количество команд на такт ), сравнимая с RISC регистровыми машинами, с гораздо более высокой плотностью кода (поскольку адреса операндов неявны).
Компактный код стековой машины естественным образом умещает в кэше больше инструкций и, следовательно, может обеспечить более высокую эффективность кеша, снижая затраты на память или позволяя использовать более быстрые системы памяти при заданной стоимости. Кроме того, большинство инструкций стековой машины очень просты и состоят из одного поля кода операции или одного поля операнда. Таким образом, стековым машинам требуется очень мало электронных ресурсов для декодирования каждой инструкции.
Одна проблема, поднятая в ходе исследования, заключалась в том, что для выполнения работы инструкции RISC регистровой машины требуется около 1,88 инструкций стековой машины. Поэтому конкурирующие вышедшие из строя стековые машины требуют примерно вдвое больше электронных ресурсов для отслеживания инструкций («станций выдачи»). Это может быть компенсировано экономией в кэше инструкций, памяти и схемах декодирования инструкций.
Некоторые простые стековые машины имеют конструкцию микросхемы, которая полностью настраивается вплоть до уровня отдельных регистров. Регистр адреса вершины стека и N буферов данных вершины стека построены из отдельных индивидуальных цепей регистров с отдельными сумматорами и специальными соединениями.
Однако большинство стековых машин построено из более крупных схемных компонентов, где N буферов данных хранятся вместе в файле регистров и совместно используют шины чтения / записи. Декодированные инструкции стека отображаются в одно или несколько последовательных действий с этим скрытым файлом регистров. Нагрузки и операции ALU воздействуют на несколько самых верхних регистров, а неявные сбросы и заполнения действуют на самые нижние регистры. Декодер позволяет сделать поток команд компактным. Но если бы в потоке кода вместо этого были явные поля выбора регистра, которые напрямую управляли базовым файлом регистров, компилятор мог бы лучше использовать все регистры, и программа работала бы быстрее.
Микропрограммные стековые машины являются примером этого. Внутренний механизм микрокода - это своего рода RISC-подобная машина регистров или VLIW -подобная машина, использующая несколько файлов регистров. При непосредственном управлении микрокодом для конкретной задачи этот механизм выполняет гораздо больше работы за цикл, чем при косвенном управлении эквивалентным кодом стека для той же задачи.
Трансляторы объектного кода для HP 3000 и Tandem T / 16 - еще один пример. Они преобразовали последовательности кода стека в эквивалентные последовательности кода RISC. Незначительные «локальные» оптимизации устранили большую часть накладных расходов на стековую архитектуру. Для исключения повторных вычислений адресов использовались резервные регистры. В переведенном коде все еще сохранялось много накладных расходов на эмуляцию из-за несоответствия между исходной и целевой машинами. Несмотря на это бремя, эффективность цикла транслированного кода соответствовала эффективности цикла исходного кода стека. А когда исходный код был перекомпилирован прямо на регистровую машину с помощью оптимизирующих компиляторов, эффективность удвоилась. Это показывает, что архитектура стека и ее неоптимизирующие компиляторы расходовали более половины мощности базового оборудования.
Файлы регистров - хорошие инструменты для вычислений, потому что они имеют высокую пропускную способность и очень низкую задержку по сравнению со ссылками на память через кеши данных. В простой машине регистровый файл позволяет читать два независимых регистра и записывать третий за один цикл ALU с задержкой в один цикл или меньше. Принимая во внимание, что соответствующий кэш данных может запускать только одно чтение или одну запись (не обе) за цикл, а чтение обычно имеет задержку в два цикла ALU. Это одна треть пропускной способности при двойной задержке конвейера. В сложной машине, такой как Athlon, которая выполняет две или более инструкций за цикл, регистровый файл позволяет читать четыре или более независимых регистров и записывать два других за один цикл ALU с задержкой в один цикл. В то время как соответствующий двухпортовый кэш данных может запускать только два чтения или записи за цикл с несколькими циклами задержки. Опять же, это треть пропускной способности регистров. Создание кеша с дополнительными портами очень дорого.
Интерпретаторы для виртуальных стековых машин часто медленнее, чем интерпретаторы для других стилей виртуальных машин. Это замедление является наиболее сильным при работе на хост-машинах с глубокими конвейерами выполнения, такими как современные чипы x86.
Программа должна выполнять больше инструкций при компиляции в стековую машину, чем при компиляции в регистровую машину или машину с памятью в память. Каждая загрузка переменной или константа требует своей собственной отдельной инструкции загрузки, вместо того, чтобы быть объединенной в инструкции, которая использует это значение. Разделенные инструкции могут быть простыми и более быстрыми, но общее количество инструкций все же выше.
В некоторых интерпретаторах интерпретатор должен выполнить N-позиционный переход переключателя, чтобы декодировать следующий код операции и перейти к его шагам для этого конкретного кода операции. Другой метод выбора кодов операций - это многопоточный код. Механизмы предварительной выборки хост-машины не могут предсказать и получить цель этого индексированного или косвенного перехода. Таким образом, конвейер выполнения на главной машине должен перезапускаться каждый раз, когда размещенный интерпретатор декодирует другую виртуальную инструкцию. Это происходит чаще для машин с виртуальным стеком, чем для других стилей виртуальных машин.
Виртуальная машина Android Dalvik для Java использует 16-битный набор команд виртуального регистра вместо обычного 8- код битового стека, чтобы минимизировать количество инструкций и задержки отправки кода операции. Арифметические инструкции напрямую выбирают или сохраняют локальные переменные через 4-битные (или более крупные) поля инструкций. Версия 5.0 Lua заменила свою виртуальную стековую машину на более быструю виртуальную регистровую машину.
С тех пор, как виртуальная машина Java стала популярной, микропроцессоры использовали усовершенствованные предикторы ветвления для косвенных переходов. Это усовершенствование позволяет избежать большинства перезапусков конвейера из N-образных переходов и устраняет большую часть затрат на подсчет инструкций, которые влияют на интерпретаторы стека.
(Их не следует путать с гибридными компьютерами, которые объединяют как цифровые, так и аналоговые функции, например, иначе цифровой компьютер, который обращается к аналоговому умножению или решению дифференциальных уравнений путем отображения памяти и преобразования во входы и выходы аналогового устройства.)
Чистые стековые машины совершенно неэффективны для процедур, которые обращаются к нескольким полям одного и того же объекта. Машинный код стека должен перезагружать указатель объекта для каждого вычисления указателя + смещения. Обычное исправление для этого - добавление некоторых функций регистровой машины к стековой машине: видимый файл регистров, предназначенный для хранения адресов, и инструкции в стиле регистров для выполнения загрузок и простых вычислений адресов. Редко бывает, чтобы регистры были полностью универсальными, потому что тогда нет веских причин иметь стек выражений и инструкции постфикса.
Другой распространенный гибрид - начать с архитектуры регистровой машины и добавить еще один режим адресации памяти, который имитирует операции push или pop стековых машин: 'memaddress = reg; reg + = instr.displ '. Впервые это было использовано в миникомпьютере DEC PDP-11. Эта функция была перенесена в компьютеры VAX и в микропроцессоры Motorola 6800 и M68000. Это позволило использовать более простые методы стека в ранних компиляторах. Он также эффективно поддерживал виртуальные машины с использованием интерпретаторов стека или многопоточного кода. Однако эта функция не помогла собственному коду регистровой машины стать таким же компактным, как код чистой стековой машины. Кроме того, скорость выполнения была меньше, чем при хорошей компиляции в регистровую архитектуру. Менять указатель вершины стека только изредка (один раз за вызов или возврат) быстрее, чем постоянно повышать и опускать его на протяжении каждого оператора программы, и еще быстрее полностью избежать ссылок на память.
Совсем недавно так называемые стековые машины второго поколения приняли специальный набор регистров, которые служат в качестве адресных регистров, снимая с себя задачу адресации памяти из стека данных. Например, MuP21 использует регистр под названием «A», в то время как новейшие процессоры GreenArrays используют два регистра: A и B.
Семейство микропроцессоров Intel x86 имеет набор команд регистрового стиля (аккумулятор). for most operations, but use stack instructions for its x87, Intel 8087 floating point arithmetic, dating back to the iAPX87 (8087) coprocessor for the 8086 and 8088. That is, there are no programmer-accessible floating point registers, but only an 80-bit wide, 8 deep stack. The x87 relies heavily on the x86 CPU for assistance in performing its operations.
Examples of stack instruction sets directly executed in hardware include
Примеры виртуальных стековых машин, интерпретируемых программно:
Большинство современных компьютеров (из любой стиль набора инструкций), и большинство компиляторов используют большой стек вызова-возврата в памяти для организации кратковременных локальных переменных и ссылок возврата для всех текущих активных процедур или функций. Каждый вложенный вызов создает в памяти новый кадр стека, который сохраняется до завершения этого вызова. Этот стек вызовов-возврата может полностью управляться аппаратным обеспечением с помощью специальных регистров адреса и специальных режимов адресации инструкций. Или это может быть просто набор соглашений, использующих общие регистры и режимы регистр + смещение. Или это может быть что-то среднее.
этот метод сейчас универсален, даже на регистровых машинах, бесполезно называть все эти машины стековыми. Этот термин обычно зарезервирован для машин, которые также используют стековые и арифметические инструкции только для стека для частей одного оператора.
Компьютеры обычно обеспечивают самый эффективный доступ к глобальным переменным программам и к локальным переменным только текущим внутренним процедурам или функциям самого верхнего уровня стека. Адресация «верхнего» содержимого фреймов стека вызывающего уровня обычно не требуется и не поддерживается напрямую аппаратным оборудованием. При необходимости компиляции это, передаваемые указатели кадров в качестве дополнительных скрытых параметров.
Некоторые стековые машины Burroughs действительно используются в системе внутреннего уровня страны со специализированными режимами адресов и специальным файлом регистров представления, содержащим адреса фреймов всех внешних видимости. Никакие последующие компьютерные линейки не сделали этого аппаратно. Когда Никлаус Вирт разработал первый компилятор Pascal для CDC 6000, он обнаружил, что в совокупности указатели кадров в виде цепочки, чем постоянное обновление полных массивов указателей кадров. Этот программный метод также обозначенных накладных расходов для распространенных языков, таких как C, в которых отсутствуют ссылки верхнего уровня.
Те же машины Burroughs также поддерживали вложение задач или потоков. Задача, созданная для создания собственных кадры задач. Это было подтверждено стогом кактусов, схема расположения которого напоминала ствол и руки кактуса Сагуаро. У каждой задачи был свой сегмент памяти, как ее стек и принадлежащие ей фреймы. Основание этого стека с серединой стека его создателя. В одной куче.
В некоторых языках программирования внешняя среда данных не всегда вложена во времени. Эти языки организуют свои «записи активации» как отдельные объекты кучи, а не как фреймы стека, добавленные к линейному стеку.
На простых языках, как Forth, в которых отсутствуют локальные переменные и таких параметров, кадры стека не будут содержать ничего, кроме адресов переходов возврат и накладных расходов на управление кадрами. Поэтому их стек возврата содержит голые адреса с возвратом, а не фреймы. Стек возврата отделен от стека значений данных, чтобы улучшить процесс установки и вызова.