4.2. СИСТЕМА КОМАНД

К оглавлению1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 

 

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

Итак, рассмотрим структуру команды «Е97» (рис. 4.20). В зависимости от конкретной операции, ее формат может иметь некоторые особенности, но в наиболее полной форме он состоит из четырех частей по 4 бита каждая (см. рис. 4.20, б): модификатор МОД, код операции КОП и два операнда ОП1 и ОП2. Назначение КОП и операндов было описано в предыдущем параграфе. Что же касается МОД, то он указывает варианты реализации команды, например, адресовать байт или слово, по каким управляющим битам переходить и др.

Наиболее простой формат команд из всех возможных, имеют две -нет операции (ее код 0) и останов (код F). Как видно из рис. 4.20, а, в этих командах задействован только КОП. остальные 12 бит значения не имеют. Основная масса команд, коды которых заключены в интервале от 1 до В. являются двухадресными и соответствуют уже упоминавшемуся ранее рис. 4.16, б. К ним относятся:

1 - перепись,                  5 - умножение,                        9 - исключающее «ИЛИ»,

2 - сложение,                 6 - деление,                             А - ввод из порта,

3 - вычитание,               7 - логическое «И»,                 В - вывод из порта.

4 - сравнение,                8 - «ИЛИ»,

Рис. 4.20. Форматы команд учебного процессора «Е97»

 

Операция переписи выполняется достаточно тривиально: информация считывается из ОП1 и копируется в ОП2. Совершенно аналогично работают ввод и вывод из порта, с той лишь разницей, что в качестве одного из операндов указывается номер порта. Все остальные двухадресные команды с кодами 2-9 представляют собой определенные действия над двумя данными, выполняемые по универсальной схеме

ОП2 операция ОП 1 => ОП2

Например, по команде деления процессор извлекает ОП2, делит его на ОП1 и результат помещает вместо первоначального значения ОП2.

Некоторую особенность имеет команда сравнения. При ее исполнении производится вычитание ОП2 - ОП1, но результат никуда не записывается. («Тогда для чего же вычитать?» - спросите вы? - «Исключительно ради установки управляющих битов, которые в дальнейшем могут быть проанализированы командами условных переходов».)

Арифметические действия осуществляются над целыми числами и результаты их -целочисленные в формате «16-битные целые числа со знаком». При делении получается целая часть частного. Что же касается операций над вещественными числами, то они могут быть реализованы программным путем (соответствующие программы могут быть, например, помещены в одно из ПЗУ).

Перейдем теперь к рассмотрению команд переходов. Как мы уже знаем, они бывают абсолютные, когда значение адреса для перехода задается явно, и относительные. когда адрес следующей команды вычисляется путем значения текущего программного счетчика и указанного в теле команды смещения. В соответствии с этим в «Е97» есть два типа переходов с кодами операций С и D; их форматы представлены на рис. 4.20, в, г.

Начнем с абсолютного перехода, код которого равен С. Если процессор встретит в программе команду из двух слов

1C0D

0056

то следующей будет выполняться команда с адресом 56. Иными словами, адрес перехода берется из самой команды. В команде 1C0D старшая шестнадцатеричная цифра - модификатор, соответствующий безусловному переходу; С - код операции; 0 - неиспользуемая цифра; D - операнд, указывающий что адрес перехода хранится в следующем слове, составляющем с 1C0D единое целое. Подробности такого способа адресации - в следующем пункте.

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

1D06

Для определенности будем считать, что эта команда находится в памяти по адресу 42. В строгом соответствии с основным алгоритмом работы процессора, после выборки рассматриваемой команды счетчик адреса команд PC автоматически увеличивается до 44. Затем, выполняя расшифрованную команду перехода, процессор прибавит к текущему содержимому PC смещение 06 и тем самым осуществит переход на адрес 44 + 6 = 4А. Обратите внимание, что итоговый адрес в случае относительного перехода зависит от расположения команды перехода в ОЗУ.

При отрицательном смещении возможно получение адреса меньшего, чем исходный. При обсуждении команд перехода мы незаметно включили в работу модификатор команд. Для переходов его роль проста и наглядна: МОД показывает, по какому условию осуществляется переход. Таблица всех используемых в «Е97» значений модификаторов выглядит так:

0   -   возврат из подпрограммы;

1    -   безусловный переход;

2    -    N = 0 (≥0);

3    -   N = 1 (<0);

4    -    Z = 0 (≠0);

5    -   Z = 1 (=0);

6    -   N=1 orZ=l (≤0);

'7    -   N=0andZ=0(>0);

9   -   вызов подпрограммы.

 

Становится очевидным, что рассмотренные в обоих предыдущих примерах команды с МОД = 1 являются наиболее простым вариантом перехода - безусловным.

Для работы с условными переходами следует твердо запомнить следующее правило:

«Если анализируемое условие справедливо, т. е. состояние управляющих признаков совпадает с требуемым, то переход происходит. В противном случае никаких действий не производится, а значит переход просто игнорируется и процессор, как обычно, выбирает следующую команду».

Кстати, так обстоит дело и в языках высокого уровня.

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

Наиболее важное отличие перехода к подпрограмме от безусловного перехода состоит в том, что требуется иметь возможность вернуться из подпрограммы в то же самое место, откуда она была вызвана. Применительно к процессору возможность возврата означает запоминание где-нибудь значения программного счетчика PC; для возврата достаточно будет просто восстановить в PC сохраненное значение.

Для обеспечения возможности вложения друг в друга подпрограмм необходимо уметь сохранять не одно значение PC, а несколько. Для реализации такого механизма памяти используется стек, который идеально подходит для любой вложенности конструкций и при этом требует наличия всего одного выделенного регистра-указателя стека SP.

Рассмотрим конкретный пример. Пусть в некотором месте программы находится команда из двух слов

9C0D

0030

Исполнять эту команду процессор будет так. Прежде всего, он уменьшит SP на 2 и запомнит по полученному адресу текущее содержимое PC (вспомните, что счетчик к этому времени уже будет показывать на следующую команду). Затем последует переход по адресу 30, считанному ранее из второго слова команды. Таким способом мы попадем в подпрограмму, надежно спрятав в стеке адрес основной программы, куда нужно вернуться. Обсудим теперь, как произойдет возврат.

В конце любой подпрограммы должна стоять команда 0С00 или 0D00. Встретив ее. процессор извлечет из стека занесенное туда ранее значение и поместит его в PC. При этом он увеличит SP на два, освободив ненужную более ячейку памяти в стеке. Таким образом, прерванное на время выполнение основной программы продолжится с нужного места.

Примечание. Команды с кодами 0С и 0D тождественны и их младшие 8 бит не используются.

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

Займемся последней группой команд процессора, для которой КОП = Е. Прежде всего, почему такому КОП соответствует группа, а не одна команда? Все дело в том, что эти команды одноадресные, и освобождающиеся от одного из операндов 4 бита можно использовать для задания номера операции в этой группе. Назовем полученные биты дополнением к КОП - ДКОП. В итоге получим формат, приведенный на рис.4.20, д). Из рисунка видно, что код операций для всех одноадресных операций состоит из двух шестнадцатеричных цифр, причем первая из них всегда Е. Познакомимся с этими командами более подробно.

Команда с кодом Е1 выполняет над единственным операндом ОП1 логическую операцию НЕ, т.е. заменяет нулевые биты единицами и наоборот (инверсия).

Команды с кодами Е2 - Е9 обеспечивают работу со стеком. Так, при коде операции Е2 ОП1 заносится в стек, а при ЕЗ - считывается оттуда. Например, вот как можно поменять местами содержимое регистров R1 и R2 с использованием стека:

 

0000   0Е21      записать R1 в стек

0002   0Е22      записать R2 в стек

0004   0Е31      считать значение из стекав R1

0006   0Е32      считать значение из стека в R2

0008   0F00      останов

 

Команды Е4 и Е5 позволяют изменять значение SP на величину ОП1, что часто бывает полезно при работе со стеком, например, при освобождении в нем сразу нескольких «этажей». По кодам Е6 и Е7 можно задать новое значение SP и прочитать его текущее значение в ОП1. Наконец, наиболее экзотические из этой группы команды Е8 и Е9 сохраняют в стеке и восстанавливают для последующего анализа регистр состояния процессора PS. Эти команды замечательны тем, что обрабатывают вполне определенный операнд, поэтому содержимое ОП1 в команде значения не имеет; договоримся заполнять его нулем.

Осталось рассмотреть последнюю группу команд - сдвиги. Их коды ЕА - ЕС. Все они осуществляют сдвиг кода в ОП1 на один разряд влево или вправо в зависимости от значения ДКОП. Полезно помнить, что сдвиг влево эквивалентен умножению, а вправо - делению на два.

Команда ЕС, называемая арифметическим сдвигом, отличается от обычного сдвига ЕВ тем, что старший знаковый разряд при арифметическом сдвиге сохраняет свое значение, например:

Исходное значение ОП 1: 1111 0000 1111 0000

Результат команды ЕВ:   0111 1000 0111 1000

Результат команды ЕС:   1111 1000 0111 1000.

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

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

 

 

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

Итак, рассмотрим структуру команды «Е97» (рис. 4.20). В зависимости от конкретной операции, ее формат может иметь некоторые особенности, но в наиболее полной форме он состоит из четырех частей по 4 бита каждая (см. рис. 4.20, б): модификатор МОД, код операции КОП и два операнда ОП1 и ОП2. Назначение КОП и операндов было описано в предыдущем параграфе. Что же касается МОД, то он указывает варианты реализации команды, например, адресовать байт или слово, по каким управляющим битам переходить и др.

Наиболее простой формат команд из всех возможных, имеют две -нет операции (ее код 0) и останов (код F). Как видно из рис. 4.20, а, в этих командах задействован только КОП. остальные 12 бит значения не имеют. Основная масса команд, коды которых заключены в интервале от 1 до В. являются двухадресными и соответствуют уже упоминавшемуся ранее рис. 4.16, б. К ним относятся:

1 - перепись,                  5 - умножение,                        9 - исключающее «ИЛИ»,

2 - сложение,                 6 - деление,                             А - ввод из порта,

3 - вычитание,               7 - логическое «И»,                 В - вывод из порта.

4 - сравнение,                8 - «ИЛИ»,

Рис. 4.20. Форматы команд учебного процессора «Е97»

 

Операция переписи выполняется достаточно тривиально: информация считывается из ОП1 и копируется в ОП2. Совершенно аналогично работают ввод и вывод из порта, с той лишь разницей, что в качестве одного из операндов указывается номер порта. Все остальные двухадресные команды с кодами 2-9 представляют собой определенные действия над двумя данными, выполняемые по универсальной схеме

ОП2 операция ОП 1 => ОП2

Например, по команде деления процессор извлекает ОП2, делит его на ОП1 и результат помещает вместо первоначального значения ОП2.

Некоторую особенность имеет команда сравнения. При ее исполнении производится вычитание ОП2 - ОП1, но результат никуда не записывается. («Тогда для чего же вычитать?» - спросите вы? - «Исключительно ради установки управляющих битов, которые в дальнейшем могут быть проанализированы командами условных переходов».)

Арифметические действия осуществляются над целыми числами и результаты их -целочисленные в формате «16-битные целые числа со знаком». При делении получается целая часть частного. Что же касается операций над вещественными числами, то они могут быть реализованы программным путем (соответствующие программы могут быть, например, помещены в одно из ПЗУ).

Перейдем теперь к рассмотрению команд переходов. Как мы уже знаем, они бывают абсолютные, когда значение адреса для перехода задается явно, и относительные. когда адрес следующей команды вычисляется путем значения текущего программного счетчика и указанного в теле команды смещения. В соответствии с этим в «Е97» есть два типа переходов с кодами операций С и D; их форматы представлены на рис. 4.20, в, г.

Начнем с абсолютного перехода, код которого равен С. Если процессор встретит в программе команду из двух слов

1C0D

0056

то следующей будет выполняться команда с адресом 56. Иными словами, адрес перехода берется из самой команды. В команде 1C0D старшая шестнадцатеричная цифра - модификатор, соответствующий безусловному переходу; С - код операции; 0 - неиспользуемая цифра; D - операнд, указывающий что адрес перехода хранится в следующем слове, составляющем с 1C0D единое целое. Подробности такого способа адресации - в следующем пункте.

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

1D06

Для определенности будем считать, что эта команда находится в памяти по адресу 42. В строгом соответствии с основным алгоритмом работы процессора, после выборки рассматриваемой команды счетчик адреса команд PC автоматически увеличивается до 44. Затем, выполняя расшифрованную команду перехода, процессор прибавит к текущему содержимому PC смещение 06 и тем самым осуществит переход на адрес 44 + 6 = 4А. Обратите внимание, что итоговый адрес в случае относительного перехода зависит от расположения команды перехода в ОЗУ.

При отрицательном смещении возможно получение адреса меньшего, чем исходный. При обсуждении команд перехода мы незаметно включили в работу модификатор команд. Для переходов его роль проста и наглядна: МОД показывает, по какому условию осуществляется переход. Таблица всех используемых в «Е97» значений модификаторов выглядит так:

0   -   возврат из подпрограммы;

1    -   безусловный переход;

2    -    N = 0 (≥0);

3    -   N = 1 (<0);

4    -    Z = 0 (≠0);

5    -   Z = 1 (=0);

6    -   N=1 orZ=l (≤0);

'7    -   N=0andZ=0(>0);

9   -   вызов подпрограммы.

 

Становится очевидным, что рассмотренные в обоих предыдущих примерах команды с МОД = 1 являются наиболее простым вариантом перехода - безусловным.

Для работы с условными переходами следует твердо запомнить следующее правило:

«Если анализируемое условие справедливо, т. е. состояние управляющих признаков совпадает с требуемым, то переход происходит. В противном случае никаких действий не производится, а значит переход просто игнорируется и процессор, как обычно, выбирает следующую команду».

Кстати, так обстоит дело и в языках высокого уровня.

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

Наиболее важное отличие перехода к подпрограмме от безусловного перехода состоит в том, что требуется иметь возможность вернуться из подпрограммы в то же самое место, откуда она была вызвана. Применительно к процессору возможность возврата означает запоминание где-нибудь значения программного счетчика PC; для возврата достаточно будет просто восстановить в PC сохраненное значение.

Для обеспечения возможности вложения друг в друга подпрограмм необходимо уметь сохранять не одно значение PC, а несколько. Для реализации такого механизма памяти используется стек, который идеально подходит для любой вложенности конструкций и при этом требует наличия всего одного выделенного регистра-указателя стека SP.

Рассмотрим конкретный пример. Пусть в некотором месте программы находится команда из двух слов

9C0D

0030

Исполнять эту команду процессор будет так. Прежде всего, он уменьшит SP на 2 и запомнит по полученному адресу текущее содержимое PC (вспомните, что счетчик к этому времени уже будет показывать на следующую команду). Затем последует переход по адресу 30, считанному ранее из второго слова команды. Таким способом мы попадем в подпрограмму, надежно спрятав в стеке адрес основной программы, куда нужно вернуться. Обсудим теперь, как произойдет возврат.

В конце любой подпрограммы должна стоять команда 0С00 или 0D00. Встретив ее. процессор извлечет из стека занесенное туда ранее значение и поместит его в PC. При этом он увеличит SP на два, освободив ненужную более ячейку памяти в стеке. Таким образом, прерванное на время выполнение основной программы продолжится с нужного места.

Примечание. Команды с кодами 0С и 0D тождественны и их младшие 8 бит не используются.

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

Займемся последней группой команд процессора, для которой КОП = Е. Прежде всего, почему такому КОП соответствует группа, а не одна команда? Все дело в том, что эти команды одноадресные, и освобождающиеся от одного из операндов 4 бита можно использовать для задания номера операции в этой группе. Назовем полученные биты дополнением к КОП - ДКОП. В итоге получим формат, приведенный на рис.4.20, д). Из рисунка видно, что код операций для всех одноадресных операций состоит из двух шестнадцатеричных цифр, причем первая из них всегда Е. Познакомимся с этими командами более подробно.

Команда с кодом Е1 выполняет над единственным операндом ОП1 логическую операцию НЕ, т.е. заменяет нулевые биты единицами и наоборот (инверсия).

Команды с кодами Е2 - Е9 обеспечивают работу со стеком. Так, при коде операции Е2 ОП1 заносится в стек, а при ЕЗ - считывается оттуда. Например, вот как можно поменять местами содержимое регистров R1 и R2 с использованием стека:

 

0000   0Е21      записать R1 в стек

0002   0Е22      записать R2 в стек

0004   0Е31      считать значение из стекав R1

0006   0Е32      считать значение из стека в R2

0008   0F00      останов

 

Команды Е4 и Е5 позволяют изменять значение SP на величину ОП1, что часто бывает полезно при работе со стеком, например, при освобождении в нем сразу нескольких «этажей». По кодам Е6 и Е7 можно задать новое значение SP и прочитать его текущее значение в ОП1. Наконец, наиболее экзотические из этой группы команды Е8 и Е9 сохраняют в стеке и восстанавливают для последующего анализа регистр состояния процессора PS. Эти команды замечательны тем, что обрабатывают вполне определенный операнд, поэтому содержимое ОП1 в команде значения не имеет; договоримся заполнять его нулем.

Осталось рассмотреть последнюю группу команд - сдвиги. Их коды ЕА - ЕС. Все они осуществляют сдвиг кода в ОП1 на один разряд влево или вправо в зависимости от значения ДКОП. Полезно помнить, что сдвиг влево эквивалентен умножению, а вправо - делению на два.

Команда ЕС, называемая арифметическим сдвигом, отличается от обычного сдвига ЕВ тем, что старший знаковый разряд при арифметическом сдвиге сохраняет свое значение, например:

Исходное значение ОП 1: 1111 0000 1111 0000

Результат команды ЕВ:   0111 1000 0111 1000

Результат команды ЕС:   1111 1000 0111 1000.

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

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