В предыдущей главе мы рассмотрели общую структуру вычислительной машины.
Предметом данной книги прежде всего является устройство ЭВМ и программирование на языке ассемблера. Для усвоения основных понятий необходимо хорошо изучить структуру какой-либо реальной системы. С целью иллюстрации этих основных понятий мы избрали вычислительные машины Систем 360 и 370, которые являются представителями современного поколения вычислительных машин. Несмотря на то что Системы 360 и 370 имеют разные имена, с точки зрения программиста они идентичны. Все команды, написанные для Системы 360, корректны и на Системе 370. Таким образом, научившись программировать на машинах Системы 360, мы будем в состоянии использовать почти все возможности Системы 370. Все программы, написанные для Системы 360, могут быть выполнены и на машинах Системы 370.
Тем не менее обратное не верно. Некоторые команды Системы 370 не имеют аналогов на Системе 360. В частности, для машин Системы 370 существуют команды, позволяющие достичь большей гибкости при манипуляциях с символьной информацией, и команды счета с повышенной точностью. Программы, содержащие эти команды, не могут быть выполнены на Системе 360.
Поскольку эти два ряда имеют так много общего, мы будем вместо ссылок на их полные названия использовать сокращения «IBM360/370», «IBM360» или просто «ЭВМ». Мы будем специально выделять команды, действительные только для IBM370, если такие будут встречаться в тексте.
Существуют две основные причины, по которым именно IBM360/370 были выбраны для нашего рассмотрения. Во-первых, эти машины очень распространены; более 50% всех средних и крупных вычислительных машин мира составляют именно они. В вычислительных центрах высших учебных заведений этот процент еще выше, так что весьма велика вероятность, что студент, изучающий структуру и язык ассемблера IBM360, сможет применить свои знания на практике еще в учебном заведении, а затем и по его окончании. Второй причиной является то, что машины IBM360 по своей структуре являются типичными представителями машин своего класса. То есть все основные особенности IBM360 могут быть найдены, вероятно несколько модифицированные и переименованные, в любой современной вычислительной системе.
Имея это в виду, становится ясно, что нет никакой необходимости везде отмечать, присуще ли обсуждаемое свойство IBM360 всем остальным машинам или нет. Читатель не должен получить представление, что IBM360 — единственная машина в мире, но должен иметь в виду, что если он действительно много знает о IBM360, то большая часть его знаний применима и к другим современным машинам.
Приступим теперь к изучению вычислительных машин семейства IBM360 и их языка ассемблера. Наибольший интерес как центральная часть ЭВМ представляет устройство управления. Знание основных функций и принципов работы CPUявляется необходимым для программирования на языке ассемблера и позволяет программисту, применяя другие языки, более эффективно использовать вычислительную систему в целом. В этом разделе мы рассмотрим структуру и функции устройств управления более подробно.
Машинный язык
Как и вся внутренняя информация, команды машинного языка, пригодные для обработки устройством управления, представлены в форме последовательностей двоичных цифр. Команды машинного языка состоят из двух частей, или полей. Первое поле — поле операции, указывающее операцию, выполняемую по данной команде. Следующее поле — поле операндов, которое обычно содержит адреса операндов.
Поле операции состоит из 8 битов, которые представляют код операции. Одна из частей процесса обработки команд устройством управления состоит в преобразовании кода операции в электрические сигналы, необходимые для выполнения данной операции. Например, двоичным кодом операции сложения двух целых чисел, одно из которых находится в регистре, а другое в памяти, является
тогда как кодом операции пересылки содержимого некоторой группы ячеек в другое место памяти является
11010010
В общем, каждая машинная операция имеет свой код. На рис. 2.2 представлен перечень операций вместе с соответствующими кодами. В целях упрощения конструкции машины и наглядности машинного языка однотипные операции получили близкие коды. Например, код операции сложения 01011010 лишь последним битом отличается от кода операции вычитания 01011011. Аналогичные примеры можно найти на рис. 2.2.
Как уже было отмечено в предыдущем разделе, операнды обычно определяются заданием адреса ячейки или номера регистра. В полях операндов машинных команд адреса указываются в виде двоичных целых. Например, когда говорят о «содержимом регистра 5», в машинной команде указывается число 0101, двоичное представление 01011010
Рис. 2.2. Некоторые операции и их коды.
числа 5, а «содержимое ячейки 105» представляется в команде числом 01101001, являющимся двоичной формой записи числа 105.
Итак, команда машинного языка содержит два поля, поле операции и поле операндов. В поле операции указывается двоичный код требуемой операции, а в поле операндов — их адреса в двоичной форме.
Счетчик команд
Программа хранится в памяти машины. Обычно устройство управления выполняет команды в той последовательности, в какой оно выбирает их из памяти. Но как узнать, где находится команда, которую необходимо выполнить вслед за обрабатываемой?
Счетчик команд содержит адрес следующей команды, подлежащей обработке. Одной из составных частей цикла обработки команд устройством управления является определение адреса следующей команды. Когда обработка текущей команды завершена, производится выборка следующей команды из ячейки памяти, указанной в счетчике команд, и помещение ее в специальный регистр, регистр команд устройства управления. Затем производится замена содержимого счетчика команд на адрес «новой» следующей команды
Допустим, что мы имеем последовательность команд, расположенных в ячейках
100
102
106
112
При выполнении команды из ячейки 100 счетчик команд содержит число 102 (двоичную форму числа 102, если быть более точными). По окончании выполнения этой команды информация из ячейки 102 попадает в регистр команд, а 106 в двоичной форме — в счетчик команд.
В некоторых случаях может возникнуть необходимость изменить нормальный порядок выполнения команд, определяемый их последовательным расположением в памяти, и перейти к некоторой команде не в порядке этой обычной последовательности. Результатом выполнения команды перехода является изменение содержимого счетчика команд. Таким образом, если в ячейке 106 содержится команда перехода в ячейку 100, то результатом ее выполнения будет занесение числа 100 в счетчик команд.
Регистры общего назначения
Итак, мы рассмотрели функции двух регистров: счетчика команд и регистра команд. Счетчик команд содержит адрес следующей команды, подлежащей выполнению, регистр команд — обрабатываемую в настоящий момент команду. Содержимое этих регистров меняется при выполнении каждой команды, и поэтому эти регистры используются в качестве временной памяти для текущей информации.
Вообще, регистры служат в качестве временной памяти. Регистры имеют два характерных отличия от ячеек памяти. Во-первых, время доступа к информации, помещенной в регистр, значительно меньше, чем для ячеек памяти. Во-вторых, обычно регистры предназначены для выполнения гораздо более сложных операций, чем простое хранение информации, как это имеет место для ячеек памяти. Устройству управления «известно», что адрес следующей команды хранится именно в счетчике команд.
Регистр и счетчик команд — примеры регистров специального назначения. Изменить содержимое регистра команд или прибавить что-нибудь к содержимому счетчика команд мы не в состоянии. Другими словами, эти регистры тесно связаны с устройством управления и обычно не могут быть использованы для каких-либо иных целей, чем те, для которых они созданы.
Для увеличения скорости и гибкости обработки информации в Системе 360 предусмотрено 16 регистров общего назначения, имеющих номера от 0 до 15. Они используются в качестве связующих звеньев между устройством управления, арифметическим устройством и памятью. По крайней мере один из операндов большинства арифметических, логических команд и команд сравнения находится в регистре общего назначения. После выполнения очередной команды результат обычно оставляется в регистре 1). Регистры поэтому играют роль накопителей, или временной памяти для промежуточных результатов вычислений.
Предположим, что первоначально в регистре 3 находилось число 50. Мы хотим сложить число, находящееся в ячейке 1000, с указанным числом. Для этого могут быть использованы следующие команды:
или в машинных кодах
Результат операции будет находиться в регистре 3. Следовательно, если до выполнения операции ячейка 1000 содержала число 100, то содержимым регистра 3 после ее выполнения будет число 150. Содержимое ячейки 1000 останется неизменным.
Рассмотрим более детально процесс выполнения команды. Сначала команда попадает в регистр команд, а в счетчике команд устанавливается адрес следующей. Первый операнд выбирается из регистра 3 и посылается в арифметическое устройство. Второй — из ячейки памяти с адресом 1000 (это не меняет содержимого ячейки 1000) и также посылается в арифметическое устройство. Числа (50+100) складываются, и результат (150) заносится в регистр 3, при этом предыдущее содержимое регистра теряется.
Выписывание адресов группы операндов — дело утомительное, а зачастую и невозможное: слишком велико может быть их количество. Регистры общего назначения могут быть использованы для манипуляций с адресами в целях облегчения процесса обработки больших массивов информации.
Пусть нам надо вычислить сумму десяти тысяч чисел, расположенных в последовательных ячейках памяти. Поскольку у каждого числа свой адрес, то, значит, необходимо выполнить 10 000 команд сложения, содержащих 10 000 различных адресов операндов. Прямым способом достижения этой цели является написание для каждого числа своей команды сложения с содержимым некоторого регистра. Но поскольку числа хранятся в последовательных ячейках памяти, мы можем поручить часть работы по вычислению адресов самой ЭВМ. Поместим адрес первого числа в регистр. В дальнейшем будем использовать содержимое этого регистра в качестве адреса каждого следующего слагаемого. Теперь мы можем просто пересчитывать содержимое адресного регистра каждый раз при вычислении очередной частичной суммы.
Процедура, описанная выше, является примером цикла, или последовательности команд, выполнение которой повторяется до тех пор, пока требуемые вычисления не будут завершены. Как узнать, когда вычисления уже закончены? Обычно мы используем регистр общего назначения в качестве счетчика циклов. Мы начинаем с того, что заносим в этот регистр 0, и затем при каждом новом прохождении цикла увеличиваем его содержимое. Когда значение счетчика цикла достигает необходимого количества повторений, мы выходим из цикла.
В программировании циклы играют очень большую роль. Фактически, если бы ЭВМ не обладали возможностью циклической работы, они, вероятно, были бы бесполезны, поскольку в большинстве случаев написание программы стало бы настолько сложным и занимало бы столько времени, сколько и решение соответствующих задач «вручную». Мы упоминали процесс вычисления «среднего». Сумма чисел может быть вычислена с помощью цикла, содержащего всего лишь две команды, добавления следующего числа и увеличения и проверки содержимого счетчика цикла. Мы можем использовать один раз написанную программу для вычисления «среднего» любого количества чисел.
Если бы не было циклов, мы должны бы были написать 10 000 команд для вычисления суммы 10 000 чисел. Более того, каждый раз при изменении количества слагаемых программу приходилось бы менять. Почему бы в этом случае не использовать настольный вычислитель?
Вычисление среднего является всего лишь одним примером использования повторяемости вычислений в машине. При решении многих научных проблем требуются итерационные вычисления. Значения многих функций (функция синуса, например) вычисляются сложением последовательностей чисел. Многие способы решения уравнений заключаются в установлении начального приближения и последовательном улучшении его до тех пор, пока не будет достигнута необходимая точность. Все операции с матрицами требуют повторных вычислений. При машинной реализации метода Монте-Карло мы повторно генерируем характеристики среды, воздействующей на модель исследуемого явления. Сама реализация модели обычно содержит несколько циклов. Циклы часто используются при статистическом анализе результатов моделирования.
Большинство реальных процессов обработки данных являются циклическими по своей природе. Например, периодическое обновление текущих счетов в банках является циклическим процессом, изменяющим эти счета в соответствии со вкладами и выплатами со счетов, произошедшими со времени последней корректировки. Аналогичные операции проводятся при учете материальных ценностей, обработке сведений о студентах, налоговых ведомостей, счетов и т. д. Изменение текущего счета требует циклической работы, так как при вычислении баланса учитываются все операции подотчетного периода. Такие простые процессы, как распечатка налоговых ведомостей и счетов, также требуют циклической обработки всей информации запись за записью.
Короче говоря, практически не существует вычислительных работ, не требующих циклов. Одно из важных качеств регистров — возможность их использования для управления циклами. Регистры применяются и для хранения адресов операндов, и для контроля числа повторений. Чем лучше используются регистры, тем эффективнее общая программа.
Итак, регистры общего назначения нужны как для хранения результатов промежуточных вычислений, так и информации, периодически используемой в вычислениях. Их применение в качестве накопителей и для модификации адресов позволяет избежать значительных накладных расходов, связанных с управлением памятью.
Выполнение команд
Мы уже знаем, что устройство управления руководит потоками информации между компонентами системы и обработкой этой информации. При этом оно должно также определять последовательность выполнения операций во времени. В процессе своего функционирования устройство управления выполняет бесконечную последовательность операций. Каждый цикл работы состоит из таких шагов:
1.Выборка команды. Команда, которая должна выполняться следующей, выбирается из ячейки памяти, адрес которой указан в счетчике команд.
2.Обновление содержимого счетчика команд. В счетчик помещается адрес следующей команды.
3.Декодирование команды. По содержимому поля операции определяется операция, которую необходимо выполнить.
4.Выборка операндов. Вычисляются адреса операндов, если это необходимо, и производится перемещение операндов (например, в арифметическое устройство).
5.Выполнение операции.
6.Запоминание результатов. Результат посылается в требуемое место (например, в регистр).
7.Возврат. Последовательность шагов повторяется, начиная с шага 1.
Обычно команды программ хранятся в последовательных ячейках памяти. Обновление счетчика команд поэтому обычно состоит в приращении содержимого на величину длины команды. Иначе дело обстоит при выполнении команд перехода. Шаг «выполнение операции» этой команды заносит содержимое операнда в счетчик команд)
На самом деле в большинстве современных ЭВМ некоторые из этих шагов выполняются одновременно. Например, выборка операндов может производиться одновременно с декодированием команды, что и имеет место во многих машинах. Тем не менее основная последовательность шагов именно такова, как она была описана выше.