Команды вызова подпрограмм

Команды управления ходом выполнения программы

Концепция фон-неймановской вычислительной машины предполагает, что команды программы, как правило, выполняются в порядке их расположения в памяти. Для получения адреса очередной команды достаточно увеличить содержимое счетчика команд на длину текущей команды. В то же время основные преимущества ВМ заключаются именно в возможности изменения хода вычислений в зависимости от возникающих в процессе счета результатов. С этой целью в АСК вычислительной машины включаются команды, позволяющие нарушить естественный порядок следования и передать управление в иную точку программы. В адресной части таких команд содержится адрес точки перехода (адрес той команды, которая должна быть выполнена следующей). Переход реализуется путем загрузки адреса точки перехода в счетчик команд (вместо увеличения содержимого этого счетчика на длину команды).

Наименование операции Описание
Безусловный переход Переход на команду, размещенную в памяти по заданному адресу; загрузка в счетчик команд заданного адреса
Условный переход Анализ заданного условия и при определенном результате анализа переход на команду, размещенную в памяти по заданному адресу, т.е. загрузка в счетчик команд заданного адреса
Переход на подпрограмму Сохранение информации о текущем состоянии программы в определенном месте и переход по заданному адресу
Возврат из подпрограммы Извлечение сохраненной ранее в определенном месте информации о текущем состоянии прерванной программы и восстановление этого состояния в регистрах процессора
Выполнение Извлечение операнда из ячейки по заданному адресу и интерпретация его значения как машинной команды; счетчик команд при интерпретации операнда не изменяется
Условный пропуск Анализ заданного условия и при определенном результате анализа приращение счетчика команд, приводящее к тому, что команда, следующая за текущей, не выполняется
Останов Прекращение выполнения программы
Ожидание Прекращение выполнения программы и периодический анализ заданного условия; возобновление выполнения программы, когда обнаружится, что условие удовлетворяется
Нуль-операция Никакие действия не выполняются, но выполнение программы продолжается

Команды ветвления

Команды ветвления, называемые часто еще и командами перехода (jump), всегда содержат в качестве одного из операндов адрес следующей выполняемой команды.

Несмотря на то что присутствие в программе большого числа команд безусловного перехода считается признаком плохого стиля программирования, такие команды обязательно входят в АСК любой ВМ. Для их обозначения в языке ассемблера обычно используется английское слово jump (прыжок). Команда безусловного перехода обеспечивает переход по заданному адресу без проверки каких-либо условий. Существует два варианта команд безусловного перехода: в одном случае адресная часть команды содержит абсолютный адрес перехода, в другом – относительное смещение.

Чаще всего используются в программах команды условного перехода. Условный переход происходит только при соблюдении определенного условия, в противном случае выполняется следующая по порядку команда программы. Большинство производителей ВМ в своих ассемблерах обозначают подобные команды словом branch (ветвление). Условием, на основании которого осуществляется переход, чаще всего выступают признаки результата предшествующей арифметической или логической операции. Каждый из признаков фиксируется в своем разряде регистра флагов процессора.

Коды условий процессоров Pentium

Бит состояния Наименование Описание
С Перенос Индикатор появления переноса в старший разряд или заема из старшего разряда при выполнении арифметических операций. Модифицируется также некоторыми операциями сдвига
Р Четность Устанавливается (равен 1), когда в коде результата количество единиц — четное число
А Дополнительный перенос, полуперенос Устанавливается, когда при сложении производится перенос 1 в 4-й разряд или при вычитании производится заем 1 из 4-го разряда
Z Нуль Устанавливается, когда результат операции равен 0, т.е. все разряды в коде результата равны 0
S Знак Устанавливается, если результат операции отрицательный, т.е. самый левый разряд кода результата равен 1
О Переполнение Устанавливается, если при выполнении арифметической операции появляется переполнение

В системе команд ВМ для каждого признака результата предусматривается своя команда ветвления (чаще — две: переход при наличии признака и переход при его отсутствии). Большая часть условных переходов связана с проверкой взаимного соотношения двух величин или с равенством (неравенством) некоторой величины нулю. Последний вид проверок используется в программах наиболее интенсивно.

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

Третий вариант — это объединение операций сравнения и перехода в одной команде. Такой подход реализуется в командах трехадресного формата. Например, в команде ВРЕ R1, R2, X — «Переход на команду, размещенную в ячейке X, если содержимое R1 равно содержимому R2»

Команды пропуска

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

Поскольку в формате команды пропуска отсутствует поле адреса перехода, в ней можно представить другие операции. Типичным примером может служить команда ISZ приращения и пропуска, если результат равен 0. Рассмотрим следующий фрагмент программы:

Команды вызова подпрограмм

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

Команды вызова подпрограмм

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

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

Механизм поддержки работы с подпрограммами должен включать два основных типа команд — команды вызова подпрограммы и команды возврата из подпрограммы. Команды вызова подпрограммы должны обеспечить переход на первую команду вызываемой подпрограммы, а команды возврата — переход на команду вызывающей программы, следующую за командой вызова. Команды обоих видов относятся к категории команд управления ходом выполнения программы.

Заслуживают внимания следующие моменты.

1. Подпрограмма может быть вызвана из любого места других программных модулей. Таких вызовов может быть сколько угодно.

2. Одна подпрограмма может быть вызвана из другой, которая, в свою очередь, вызвана третьей. Это называется вложенностью (nesting) вызовов. Глубина вложенности теоретически может быть произвольной.

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

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

• регистр процессора;

• начальный адрес подпрограммы;

• верхняя ячейка стека.

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

Более общим и более надежным подходом является использование для хранения адреса возврата стека. Когда ЦП выполняет команду вызова подпрограммы, адрес возврата помещается в верхнюю ячейку стека, а когда он выполняет команду возврата, извлекает этот адрес из верхней ячейки стека.

При вызове подпрограммы, как правило, требуется не только сохранить адрес возврата, но и передать в подпрограмму значения параметров. Для этого можно воспользоваться регистрами процессора. Другой вариант — хранить параметры в памяти сразу же за командой вызова подпрограммы. В данном случае адрес возврата должен указывать на ячейку, следующую за списком параметров, а не за самой командой вызова. Каждый из этих подходов имеет свои недостатки. Если для передачи параметров используются регистры, вызывающая программа и подпрограмма должны быть спроектированы таким образом, чтобы в них обеспечивалось правильное использование этих регистров. При хранении списка параметров в памяти вслед за командой вызова сложно организовать передачу в подпрограмму количества параметров. В обоих случаях весьма затруднительно обеспечить реентерабельность подпрограмм.

Более гибкий подход предусматривает передачу параметров в подпрограмму через стек. При выполнении команды вызова подпрограммы процессор не только сохраняет в стеке адрес возврата, но и записывает в него значения параметров, которые затем могут быть извлечены из стека подпрограммой. При возврате из подпрограммы через стек можно передать и результаты ее выполнения. Набор параметров вместе с адресом возврата образует так называемый стековый кадр (stack frame).

Уроки Python для начинающих | #12 — Функции (def, lambda, return)


Похожие статьи.

Понравилась статья? Поделиться с друзьями: