Chapter_03 (1110555), страница 2
Текст из файла (страница 2)
Примеры программ для учебной машиныДалее мы рассмотрим несколько простых полных программ для нашей учебной машины. Этипрограммы призваны проиллюстрировать основные приёмы программирования на языке машиныдля первых ЭВМ, удовлетворяющих всем принципам Фон Неймана. Такие примеры позволят намлучше понять способ работы учебной ЭВМ и, следовательно, её архитектуру.
Итак, представим себяпервыми программистами .3.2.1. Пример 1. Оператор присваиванияСоставим программу, которая вводит целое число x и реализует арифметический оператор присваивания языка Паскаль:y := (x+1)2 mod (2*x)На языке Паскаль эта программа может выглядеть, например, так:Program First(input,output);Var x,y: integer;Begin Read(x); y:=sqr(x+1) mod (2*x); Writeln(y) end.Текст нашей первой программы с комментариями приведён на рис. 3.1 (напомним, что все числа– десятичные).№0012345678Команда1611131115173100101103103104102102000000001101103101103001000000Комментарий000008103101104000000001Read(x)r1 := (x+1)r1 := (x+1)2r2 := (x+x)=2*xy := r1 mod r2Write(y)СтопЦелая константа 1Рис 3.1.
Программа первого примера.Приступим теперь к записи команд нашей программы, подробно комментируя свои действия.Как мы знаем, команды нашей программы после начального ввода при нажатии кнопки ПУСК будутрасполагаться в памяти, начиная с первой ячейки. Теперь нам необходимо решить, в каких ячейкахпамяти будут располагаться наши переменные x и y. Эта работа называется распределением памяти под хранение переменных. При программировании на Паскале эту работу выполняла за насПаскаль-машина, когда видела описания переменных:Var x,y: integer;Теперь нам придётся распределять память под хранения переменных самим. Сделаем сначалаестественное предположение, что наша программа будет занимать не более 100 ячеек памяти.
Поэтому, начиная со 101 ячейки, память будет свободна. Пусть тогда для хранения значения переменной x мы выделим 101 ячейку, а переменной y – 102 ячейку памяти. Остальные переменные принеобходимости будем размещать в последующих ячейках памяти. Для реализации этой программынам понадобятся дополнительные (как говорят, рабочие) переменные r1 и r2, которые мы разместим в ячейках 103 и 104 соответственно.Поймём теперь, что при программировании на машинном языке, в отличие от Паскаля, у нас небудут существовать константы. Действительно, в какой бы ячейке мы не поместили значение константы, по принципу Фон Неймана однородности памяти ничто не помешает нам записать в этуячейку новое значение. Поэтому мы будем называть константами такие переменные, которыеимеют начальные значения, и которые мы не планируем изменять в ходе выполнения программы.5Важно понять, что в начале работы программы имеют значения только те ячейки памяти, в которые произведён ввод данных по кнопке ПУСК.1 Отсюда следует, что константы, как и переменные сначальным значением, следует располагать в тексте программы ("маскируя" их под команды) изагружать в память вместе с программой при нажатии кнопки ПУСК.
Разумеется, такие константы, ипеременные с начальными значениями следует располагать в таком месте программы, чтобы устройство управления не начало бы выполнять их как команды. Чтобы избежать этой неприятности, мыбудем размещать их в конце программы, после команды с кодом операции 31 (СТОП).Далее, мы воспользовались принципом неразличимости команд и чисел, и представили целочисленную константу 1 в виде команды 00 000 000 001 (скоро мы изучим внутреннее машинное представление целых чисел и поймём, что как машинные слова они совпадают). Этот приём позволил нам ввести эту константу, "замаскировав" её в виде команды (обычно так и поступали программисты первых ЭВМ).Следует обратить внимание и на тот факт, что изначально программист не знает, сколько ячеек впамяти будет занимать команды его программы. Поэтому адреса программы, ссылающиеся на переменные с начальным значением, до завершения написания программы командой СТОП остаются неизвестными (незаполненными), и уже потом, разместив эти переменные в памяти сразу же вслед закомандами программы, следует указать их адреса в тексте программы.
В примерах те адреса программы, которые заполняются программистом в последнюю очередь, будут выделяться подчёркиванием.Как видно из нашего примера, для программиста запись программы состоит из строк, каждаястрока снабжается номером (адресом) той ячейки, куда будет помещаться это машинной слово (команда, константа или переменная с начальным значением) при загрузке программы. Вслед за номером задаются все поля команды, затем программист может указать комментарий (разумеется, номерамашинных слов и комментарии не вводятся в память ЭВМ, для них нет места в машинном слове).Кроме того, так как числа в памяти неотличимы от команд, то, как уже говорилось, будем записывать их тоже чаще всего в виде команд.Для ввода программы в ЭВМ первые программисты кодировали все машинные слова в двоичном виде и переносили их на какой-нибудь носитель данных для устройства ввода (например, накартонные перфокарты).
После этого оставалось снабдить такую, как говорили, колоду перфокарт,перфокартой-признаком конца ввода, поместить на устройство ввода и нажать кнопку ПУСК. В нашем случае надо поместить на устройство ввода два массива машинных слов – саму программу (8машинных слов с признаком конца ввода) и число x (одно машинное слово). Как мы уже говорили,первый массив заканчивался специальным признаком конца ввода, так что устройство ввода самоузнает, сколько машинных слов надо ввести в память по кнопке ПУСК.3.2.2.
Пример 2. Условный операторСоставим теперь программу, реализующую условный оператор присваивания. Пусть целочисленная переменная y принимает значение в зависимости от значения вводимой целочисленной переменной x в соответствии с правилом:y :=x+2,при x < 2,2,при x = 2,2*(x+2), при x > 2;В данном примере при записи программы на месте кода операции мы будем для удобства вместономера указывать его мнемоническое обозначение, приведённое в таблице команд 3.1. Разумеется,потом, перед вводом программы в ЭВМ, необходимо будет заменить эти мнемонические обозначения соответствующими им двоичными числами.Для определения того, является ли значение некоторого числа x больше, меньше или равнымконстанте 2, мы будем выполнять команду вычитания x–2, получая как побочный эффект этой операции в регистре признаке результата w значение 0 при x=2, значение 1 при x<2 и значение 2 приx>2.
При этом сам результат операции вычитания x–2 нам в этой программе не нужен, но по принятому в УМ-3 формату команд указание адреса ячейки для записи результата является обязательным.1В первых ЭВМ все ячейки памяти после включения машины обычно имели полностью нулевые значения, но в нашей машине УМ-3 мы не будем этого предполагать, так же обстоит дело и в стандарте языка Паскаль, где после порождения переменные имеют неопределённые значения.6Для записи таких ненужных значений мы будем чаще всего использовать ячейку с номером 0.1 В соответствии с принципом однородности памяти, эта ячейка ничем не отличается от других, то есть,доступна как для записи, так и для чтения данных.2Для хранения переменных x и y выделим, например, ячейки 100 и 101 соответственно.
Заметим, что программист сам определяет порядок размещения в программе трёх ветвей нашего условного оператора присваивания. Мы в нашем примере будем сначала располагать вторую ветвь (дляx=2), затем первую (x<2), а потом третью (x>2). Заметим, что значение x+2 понадобится нам припрограммировании, как в первой, так и в третьей ветви условного оператора, поэтому более рационально вычисление выражения x+2 расположить перед вычислением условного оператора, что мы исделали в нашем примере. На рис. 3.2 приведён текст этой программы.№КомандаКомментарий001234ВВЦСЛЦВЧЦУСЛ100101000005001100100007000011011009567890101ВЫЦСТОПВЫЦСТОПУМЦБЕЗ00011000101000101000000001000001000011007000000000000000101000002Read(x)y := x+2<000> := x–2; формирование wCase w of 0: goto 005; 1: goto 007;2: goto 009 endWrite(2)Конец работыWrite(y)Конец работыy := 2*yGoto 007Целая константа 2Рис 3.2.
Программа второго примера.Для перехода на три ветви нашего алгоритма мы использовали команду условного перехода,предварительно вычислив предыдущей командой вычитания ВЧЦ 000 100 011 значение регистра признака результата w. Второй и третий адрес в команде условного перехода тоже подчёркнуты,так как эти значения становятся известны программисту только после написания первой (для w=0) ивторой (для w=1) ветвей нашего алгоритма соответственно.Обратите внимание, что целочисленная константа 2 располагается в таком месте программы (закомандой безусловного перехода), где она не может начать выполняться как команда.
Заметим также, что эта константа неотличима от команды ПЕР 000 000 002 для пересылки содержимоговторой ячейки памяти в нулевую ячейку, что и позволило нам записать эту константу в виде такойкоманды. Именно эта команда и выполнялась бы, если бы такая константа была (случайно) выбранана регистр команд устройства управления.Разберёмся теперь, на каком же языке мы написали наш второй пример для УМ-3. Ясно, что этоне язык машины, так как он по определению состоит только из 32-хразрядных двоичных чисел, а унас вместо кодов операции стоят мнемонические обозначения, адреса написаны в десятичной формезаписи, да ещё и комментарии присутствуют. Такой язык программирования для первых ЭВМ обычно называли псевдокодом, что хорошо отражало его сущность. Для того чтобы выполнить программу на псевдокоде, её надо предварительно перевести (или, как теперь принято говорить, оттранслировать) на язык машины.
Очевидно, что для этого необходимо заменить все мнемонические обозначения соответствующими им числовыми кодами операций, затем перевести все десятичные числав двоичную систему счисления, а также отбросить номера ячеек из первой колонки и комментарии.Для первых ЭВМ эту работу выполняли сами программисты.
В дальнейшем псевдокоды постепенноразвивались и превратились в языки низкого уровня – ассемблеры (в русскоязычной литературе ихсначала называли автокодами, подразумевая, что они автоматически переводят (кодируют)1Заметим, что в нашей архитектуре программа специально вводится в память по кнопке ПУСК, начиная спервой ячейки, оставляя программисту для подобных целей свободной ячейку с номером ноль.2В некоторых первых реальных ЭВМ этот принцип нарушался: при считывании из этой ячейки всегдавозвращался ноль, а запись в ячейку с адресом ноль физически не осуществлялась, на практике такой принципработы с этой ячейкой почти всегда был удобнее.7программу с псевдокода на язык машины).