Эмоциональная история процессоров: IBM/370

В первой части были описаны многие разные процессоры до середины 90-х. Для мейнфреймов IBM там места не нашлось, так как эти системы долгое время не использовали процессоры-чипы. Однако, мейнфреймы IBM тесно связаны с другими компьютерными системами, долгое время являясь одними из лучших образцов компьютерной техники, на которые так или иначе ориентировались практически все. Кстати, формат хабр-блога, как и Википедии, позволяет редактирование, что позволило значительно переработать содержимое первой части с учетом поступивших замечаний и прочей дополнительной информации.

В этой части главное внимание уделяется сравнению машинного языка мейнфреймов с другими системами, которые были популярны в период с 70-х по 90-е. Это прежде всего x86, 68k, VAX и ARM. Системы 390 и, в особенности, Z рассматриваются очень фрагментарно – основное внимание уделяется именно системе 370.

Первые системы 360 стали поставляться заказчикам с 1965 года, а более совершенные системы 370 с 1970. IBM поддерживает программную совместимость с этими системами до настоящего времени! Удивительно, но до систем 390, поставляемых, как можно догадаться с 1990 года, мейнфреймы работали с 24-битными адресами, т. е. могли адресовать не более 16 мегабайт памяти, столько же, сколько, например, 68000, выпущенный в 1979, или 65816 или 32016, выпущенные в 1982. VAX изначально поддерживал 32-битную адресацию. Популярные процессоры 68020 или 80386, появившись в середине 80-х, также поддерживали 32-битные адреса. Реально 16 МБ памяти для лучших систем второй половины 80-х – это было уже мало. Однако, IBM c 1983 производила совместимые с 370 вычислительные машины, которые могли как расширение использовать 31 разряд для адреса, что снимало проблему объема памяти для лучших компьютеров. Необычно и уникально, что в этих расширениях и системах 390 использовали 31-битный адрес, а не полный 32-битный. В 2000 IBM объявила о первой системе Z, где используются 64-битные адресация и данные. Системы Z стали c 2008 использовать чипы-процессоры. Архитектуру Z c 2007 пытаются соединить в одном чипе с архитектурой POWER, но пока безуспешно. Соединить CISC и RISC в одном чипе пока получилось только у Intel – Pentium Pro в 1995 стал первым чипом такого рода.

IBM System/370-145 c ленточными накопителем 2401 и принтером вместо дисплея, 1971. Может удивить отсутствие дисплея в этой очень дорогой системе при том, что телевизоры массово производятся уже более 20 лет

Кстати, некоторые авторитеты считают, что первым серийным персональным компьютером был IBM 5100, производимый с 1975, который через аппаратный эмулятор мог исполнять инструкции системы 360. Его улучшенные варианты производились до середины 80-х. Хотя скорее всё-таки первым был Wang 2200. По ценам (примерно $10000) эти первые персоналки были явно не для домашнего использования. Удивительно, но IBM 5100 с бейсиком был в несколько раз медленнее первых дешевых персональных компьютеров, например, Apple II.

IBM 5100, вариант с поддержкой языка APL

С появлением архитектуры IBM PC, которая, как оказалось, на десятилетия определила основное направление развития для вычислительной техники, IBM попыталась в 1983 соединить почти все лучшие тогда компьютерные технологии в одном изделии PC XT/370: свои системы 370, IBM PC XT, Motorola 68000 и Intel 8087. Этот XT/370 можно было использовать как интеллектуальный терминал для работы с мейнфреймом, как обычный IBM XT или для прямого запуска мейнфреймовского софта. Интересно, что в XT/370 была реализована поддержка использования виртуальной памяти, что требовало наличия двух 68000. В 1984, с появлением PC AT был выпущен улучшенный вариант "персонального мейнфрейма" AT/370, который в режиме мейнфрейма был примерно в два раза быстрее XT/370. На этом история таких систем не закончилась, с 90-х производились подобные изделия, соответствующие системам 390. Насколько мне известно, для систем Z такого уже не делали.

IBM для своих мейнфреймов использует довольно необычную для сегодняшнего дня бизнес-модель, при которой компьютеры не продаются, а сдаются в аренду. Одно из преимуществ такой модели в том, что она гарантирует постоянный апгрейд аппаратуры, устаревающая техника автоматически заменяется на обновленную соответствующего класса. У этой модели есть и недостатки. Например, особенно ощутимый недостаток для тех, кто занимается историей компьютерных технологий, – это то, что отслужившие свое компьютеры практически всегда утилизируются и поэтому их практически невозможно встретить ни в каком музее.

Удивительно было обнаружить живую систему IBM 4361 в LCM! Но есть основания предположить, что это возможно не настоящее железо. Доступ посетителей музея к этому компьютеру почему-то закрыт. Не понятно также, какая именно модель там якобы представлена, и это при том, что другие компьютеры в музее идентифицируются весьма точно. Среди систем 4361 известны три модели 3, 4 и 5, причем модель 3 появилась позже моделей 4 и 5. Но система в музее самоидентифицируется как модель 1. Возможно, что это прототип. Однако, сотрудники музея на прямой вопрос о помощи с идентификацией не ответили и это при том, что на другие и часто довольно сложные вопросы они отвечают довольно оперативно. Некоторые особенности таймингов исполнения кодов дают основания, хотя и не абсолютно твердые, предполагать, что скорее всего к сети подключен эмулятор. Летом в музее, в связи с ковид, явно перешли на эмулятор... Есть ещё шанс добраться до железных мейнфреймов через сеть HNET, но у меня пока не получилось.

Но что бы там ни было, каждый может подключиться и попробовать поработать примерно так же, как работали высокооплачиваемые специалисты с середины 70-х. Цены были такие, что сегодня трудно поверить. Например, час машинного времени стоил в середине 80-х более 20 долларов и надо было ещё доплачивать за место на дисках! Правда речь идет именно о времени работы мейнфрейма, а не терминала, через который шла работа. Поэтому, например, при редактировании текста из часа фактической работы редко набиралось и 5 минут времени на оплату. Цены на сами мейнфреймы также были фантастические. Например, сотрудники Intel вспоминают, что в начале 80-х им предоставляли для работы только один мейнфрейм. Его производительность была 10 MIPS, а цена примерно 20 миллионов тогдашних долларов, которые были раза в три тяжелее сегодняшних! Интересно, что Intel предпочитала такие компьютеры, а не более дешевые системы VAX. Сейчас даже Raspberry Pi размером с таблетку и ценой в несколько долларов может запросто выдать более 1000 MIPS. Кстати, на Raspberry Pi или практически любом современном компьютере можно запустить эмулятор IBM/370, который будет работать значительно быстрее, чем любая система IBM из 80-х или даже 90-х. Однако, эмулятор надо настраивать и не все полезные программы для IBM/370 доступны свободно, поэтому бесплатный доступ к хорошо настроенной системе – это часто лучший способ поработать с мейнфреймом. Удивительно, но такие программы для доступа, эмуляторы терминалов 3270, доступны даже на мобильниках! Между прочим, мне удалось наладить свою систему VM/CMS на эмуляторе Hercules и разобраться с переносом файлов, но это потребовало не менее недели времени.

Эмулятор Hercules может эмулировать и более поздние системы IBM/390 и IBM/Z, но из-за проблем с лицензией на программное обеспечением это сделать намного сложнее. В качестве иллюстрации таких проблем приведу известный случай, когда IBM настояла на удалении раздела Эмуляция из уже опубликованной книги! В современных электронных вариантах этой книги этого раздела нет, его можно найти только в типографском издании или отдельным файлом на сайтах, посвященных свободному ПО. Дело в том, что эмуляция на обычных персоналках с начала 2000-х могла быть заметно быстрее, чем исполнение на гораздо более дорогих мейнфреймах. IBM поэтому пришлось изменить лицензии на своё программное обеспечение так, что его можно легально использовать только на аппаратуре, купленной у IBM. Конечно, речь не идет, что эмуляторы быстрее лучших мейнфреймов, они только демонстрируют заметно лучшее отношение быстродействия к стоимости.

Один из способов поработать с системами Z или 390 – это установить Linux в эмуляторе этих систем. Для 390 и Z доступны, как минимум, дистрибутивы Ubuntu и Debian. Тут стоит заметить, что быстрое развитие Linux во многом связано со значительной поддержкой от IBM. В частности, IBM в 2001 вложила миллиард долларов в развитие Linux.

Рассмотрим теперь особенности машинного языка систем, совместимых с 360. Базовый ассемблер таких систем называют BAL – Basic Assembly Language. Удивительно, но если верить слухам об IBM, то ассемблер там до сих пор один из основных рабочих языков программирования.

Ассемблер рассматриваемых мейнфреймов имеет ряд архаических особенностей, которые в других известных архитектурах, появившихся позже, уже отсутствовали. Речь, например, идет о том, что мнемоники BAL определяют тип аргументов. Рассмотрим в качестве примера команды ассемблера x86 MOV EAX,EBX и MOV EAX,address – в обоих случаях используется мнемоника MOV. Для BAL для подобных случаев используются разные мнемоники LR и L в командах соответственно LR 0,1 и L 0,address. Однако подобные разные мнемоники позволяют использовать числа для именования регистров, хотя обычно макросы R0, R1, ... вместо чисел 0, 1, ... – это первое, что определяется в макропакетах для удобства программирования. Другой архаизм – это использование переходов по метке в конструкциях условной компиляции, хотя по моему скромному мнению – это иногда удобнее блочных структур. Но самый известный архаизм – это использование кодировки EBCDIC для работы с символьной информацией. В этой странной даже для вчерашнего дня кодировке буквы английского алфавита кодируются не подряд, например, буква I имеет код 201, а следующая за ней J – 209! Эта кодировка происходит из технологий работы с перфокартами, возникшими ещё в докомпьютерную эпоху. Система 360 на аппаратном уровне поддерживает и кодировку ASCII, но в её древнем и давно забытом варианте, где символ для цифры 0 имеет код 80, а не 48 как сейчас. Насколько мне известно, ASCII с мейнфреймами IBM лучше было даже и не пытаться использовать. Поддержку ASCII убрали уже системах 370, но ввели на новом уровне в системах 390. Некоторые мнемоники BAL поражают своей сверхкраткостью и даже немнемоничностью, например, N значит AND, O – OR, X – XOR, A – ADD, S – SUBTRACT, M – MULTIPLY, ...

Ассемблер BAL позволяет работать с тремя основными типами данных: двоичными, десятичными и вещественными числами. Системы 390 для работы с вещественными числами используют ещё один специальный тип. Некоторые системы Z могут ещё использовать и совершенно уникальные данные типа десятичные вещественные числа. Инструкции для работы с каждым типом образуют особый и довольно изолированный класс инструкций. Как правило, за очень редкими исключениями все системы, совместимые с 360, поддерживают инструкции десятичной и вещественной арифметики. Как известно, для архитектур x86 или 68k поддержка работы с вещественными числами появилась не сразу и долгое время была необязательной опцией, а работа с десятичными числами не была чем-то совершенно отдельным от двоичной арифметики – это было скорее расширение.

Для работы с вещественными и двоичными числами используют разные наборы регистров, а для работы с десятичными числами регистры не используются вообще. Система 370 предоставляет 16 32-разрядных регистров общего назначения для целых двоичных чисел, причем счетчик команд – это часть слова состояния процессора. Отдельного стека нет, его можно организовать, используя любой регистр, – так впоследствие реализовали работу со стеком и в ARM. Вызов подпрограмм также сделан как и в ARM, через регистр связи. Практически всегда все регистры взаимозаменяемые, исключения очень редки. Если сравнивать систему двоичных регистров BAL с конкурентной архитектурой VAX, то можно заметить, что у VAX на один регистр меньше. Это верно и для ARM.

Структура операндов в инструкциях покажется довольно знакомой тем, кто знает ассемблер x86. Для двоичных чисел операнды имеют структуру "регистр-регистр" или "регистр-память", причем для последнего случая из памяти можно загружать как 32-битные, так и 16-битные, расширяемые знаково, величины. Например, аналогом x86-инструкции ADD EAX,EBX будет AR 0,1, ADD EAX,addressA 0,address, ADD EAX,address[EBX]A 0,address(1), ADD EAX,address[EBX][EDX]A 0,address(1,3). Однако системы 360 и даже их поздние развитие не умеют работать с масштабированием, например, ADD EAX,address[8*EBX] на BAL одной командой не запишешь. С другой стороны, x86 не умеет работать с 16-битными знаковыми расширениями, например, команда BAL AH 0,address, которая означает взять 16-битное знаковое число из памяти и добавить его к содержимому регистра 0, на x86 потребует двух команд для своей реализации.

Редкая особенность BAL в наличии отдельных команд для сложения и вычитания для знаковых и беззнаковых чисел, причем беззнаковые операции в BAL называются логическими. Такая странность вызвана отсутствием в архитектуре 360 привычных для большинства других архитектур флагов. Вместо них используется только два бита, которые устанавливаются по-разному разными инструкциями! Разница между знаковыми и беззнаковыми операциями только в том, что они по-разному устанавливают упомянутые два бита признаков. Для знаковых операций по ним можно узнать, был ли результат равен нулю, был ли он положительный или отрицательный, произошло ли переполнение, а для беззнаковых – был ли результат равен нулю и случился ли перенос или заем. Команды условных переходов позволяют учитывать все 16 подмножеств случаев, которые возможны при использовании 2 бит. По причине такой необычной сегодня работы с признаками операций, инструкции условных переходов получаются трудными для быстрого понимания. Хотя в расширения BAL обычно добавляют довольно удобные для восприятия макросы для условных переходов, где не нужно заниматься разбором каждого из 4-х бит. Тут для справедливости можно заметить, что отдельные команды для знакового и беззнакового сложения и вычитания есть, например, в архитектуре MIPS, где вообще нет флагов!

Другая редкая особенность – в отдельных командах для знакового и беззнакового сравнения. Подобные встречал не только у MIPS, но и на MicroBlaze. В последнем, кстати, перенос – это единственный поддерживаемый флаг признаков операций.

В системах, совместимых с IBM 360, нет арифметических операций с флагом переноса, поэтому если нам нужно работать с двоичными числами, например, в 128-разрядов, то мы должны для организации их сложения или вычитания проверять признак переноса после выполнения первых 32-битных операций и делать при необходимости переход. Это, конечно, очень громоздко по сравнению с x86, ARM, 68k или даже 6502, но на гораздо более позднем MIPS – это ещё более громоздко. Нормальную работу с переносом сделали только в системе Z.

В BAL нет циклических сдвигов, зато нециклические, как и в x86, могут быть как одинарными, так и двойными. Однако, BAL имеет отдельные инструкции сдвигов для беззнаковых и знаковых чисел, только последние из них устанавливают флаги признаков. Очевидно, что результаты сдвигов влево для обоих случаев различаются только флагами. Вращения добавили только в системы 390.

Среди команд загрузки регистров в BAL есть скорее всего уникальные. Можно загружать модуль целого числа, отрицание этого модуля или число с измененным знаком – нечто отдаленно похожее мне встречалось только в архитектуре ARM. Тут стоит отметить, что вся архитектура 360 тяготеет к знаковой арифметике, а беззнаковая арифметика в этой архитектуре скорее вторична. В BAL изначально не было беззнаковых деления и умножения, их добавили только в систему 390. При загрузке регистра флаги, также как и в x86, не меняются, но есть специальная команда загрузки, которая ставит флаги – это опять напоминает ARM, где установкой флагов можно управлять.

Все знаковые арифметические операций, включая сдвиги, могут генерировать исключение при переполнении. Генерировать ли исключение или нет определяется специальным флагом маски в регистре состояния. Интересно, что двоичные деление и умножение в BAL вообще не влияют на флаги – тут можно вспомнить x86, где деление лишь портит флаги.

Поразрядные логические операции в BAL представлены обычным набором операций И, ИЛИ, исключающее ИЛИ, т. е. отдельной операции отрицания нет. Логические операции могут иметь не только структуру "регистр-регистр" или "регистр-память", но и "память-константа" или "память-память" – последний способ адресации похож на тот, что используется для десятичных чисел. Адресация типа "память-константа" возможна только для работы с байтами. Очевидно, для логических операции, в отличие от арифметических, использование 16-битных чисел невозможно. Для адресации типа "память-память" можно работать с данными длиной до 256 байт! Получается, что мы имеем три типа данных для работы с логическими операциями: байты, 32-битные слова, последовательности байт – и специальные инструкции для каждого такого типа, что скорее как-то неуниверсально.

К логическим операциям в BAL примыкают операции для пересылки байт. Помимо обычной пересылки до 256 байт одной командой, есть ещё уникальная инструкция пересылки тетрад байтов. Можно пересылать только старшие или младшие половинки байт и при этом другие половинки при копировании сохраняют своё значение! Такие странные операции нужны для поддержки особенностей BAL при работе с символьной и десятичной информацией. Есть ещё появившиеся для систем 370 команды пересылки и сравнения для до более 16 миллионов байт за один раз, которые могут прерываться. Удивительно, но также небыстрые команды по работе с блоками длиной до 256 байт прерываться не могут, что может создать неприятную своей длительностью задержку реакции на запрос на прерывание. Команды для пересылки можно использовать и для заполнения памяти заданным байтом. Помимо пересылки из памяти в память, можно ещё и устанавливать заданным значением отдельные байты. Очевидно, что команды для пересылки байт, если не рассматривать новые инструкции для 390 и Z, для x86 реализованы более продвинуто.

В регистр можно загружать не только значение по заданному адресу, но и сам адрес, как в командах LEA для x86 или 68k. Эта возможность позволяет также напрямую загружать в регистр нужную константу, хотя её максимальное значение не может быть большим 4095. Она же позволяет делать инкремент регистра на величину не более 4095. А вот декремент регистра можно делать только на 1. Как инкремент, так и декремент – это команды работы с адресом, поэтому они не меняют флаги. В регистр можно загружать и отдельные байты и даже группы байт из слова в памяти, например, только первый и третий байты – такое для всех других известных мне 32-битных архитектур возможно только через серию из 4-х команд. Аналогичным образом BAL позволяет выгружать в память только части регистра.

Ряд BAL инструкций очень специализирован – в других архитектурах такие реализуются серией более простых команд. Например, инструкция TR позволяет провести перекодировку строки символов – одним аргументом задаётся строка для перекодировки, а другим адрес перекодировочной таблицы. Особый вариант этой инструкции, TRT, можно использовать для сканирования заданной строки и пропуска пустых символов – это функциональность стандартного вызова strpos языка C. Инструкции ED и EDMK абсолютно уникальны – они имеют функциональность примитивного варианта sprintf! Однако почти все операции со строками имеют ограничение на максимальную длину строки, не более 255 байт, что значительно снижает их мощность.

В BAL из-за отсутствия команд вращения или команд типа SWAP довольно трудно работать с 16-битными беззнаковыми величинами. С систем 390 ситуация с этой проблемой стала лучше. Некоторые инструкции BAL объявлены устаревшими, например, инструкция для полубайтовых сдвигов MVO была вытеснена более удобной SRP. Для блочных пересылок и сравнений лучше использовать новые инструкции, хотя из-за того, что они используют другой способ адресации, это может быть в некоторых редких случаях неоптимальным.

Уже приводились примеры четырех основных режимов адресации BAL. Есть еще пятый для трехадресных команд. Такие режимы, как характерные для VAX, 68k, PDP-11 или даже 6809 режимы с авто-инкрементом или декрементом в BAL отсутствуют. Также нет режимов с двойным косвенным обращением к памяти, которые есть для VAX, 68020 или PDP-11. И, конечно, BAL, в отличие от ассемблеров VAX или PDP-11, совершенно неортогонален. Ближе всего BAL к ассемблерам x86 и ARM — самым успешным современным архитектурам. Порядок операндов в BAL справа-налево так же, как и в ассемблере Intel для x86 или в ассемблере ARM и, соответственно, не так как у VAX, PDP-11 или 68k. Хотя порядок байт в данных в BAL от старшему к младшему (MSB), что отличается от x86, ARM или VAX, но соответствует принятому для 68к или MIPS.

Операции с десятичными числами реализуются в BAL только через адресацию типа "память-память". Десятичные числа могут задаваться участками памяти длиной до 16 байт, что позволяет использовать числа, имеющие до 31 десятичного разряда. Это соответствует точности двоичного числа со 107 разрядами. Таким образом, только самые современные системы программирования, использующие целые двоичные числа, могут работать с большими величинами, чем системы 360 почти 60 лет назад! Конечно, можно через двоичную арифметику реализовывать сколь угодно большие числа, но популярных языков программирования, поддерживающих числа, большие, чем у древней системы 360, почему-то до недавнего времени не было. Да и сейчас поддержка 128-разрядных целых для x86 – это обычно только неофициальные расширения, как например, для GCC.

Десятичные числа на BAL представляются уникально, они должны хранить знак – такого нет для VAX, x86, 68k, ... Причем знак хранится в последнем байте представления числа! Для десятичных чисел в BAL есть непосредственная поддержка для всех основных операций: сложения, вычитания, умножения и даже деления – такого также нет ни в одной другой известной мне архитектуре. Кроме того в BAL есть ещё инструкции для копирования, сравнения и сдвигов десятичных чисел. Упоминавшаяся инструкция MVO и SRP предназначены именно для таких сдвигов. Операции могут выполняться только над упакованными десятичными числами, но для их распечатки их надо распаковать, причем и для представления распакованных цифр в BAL также необходим знак, который в этом случае не занимет места, так как помещается в старшую тетраду, что требует особой работы с этой тетрадой перед печатью. Странно, что операции для паковки и распаковки могут работать только с не более чем 16 байтами распакованного десятичного числа, что позволяет использовать с ними только не более, чем 15-разрядные числа. Эта неприятная проблема может быть решена использованием для распаковки инструкций ED или EDMK, а вот упаковку большого неупакованного числа придётся делать через не самую простую последовательность инструкций. В системы 390 добавили новые инструкции, решающме эту проблему. Любопытно, что инструкции для упаковки и распаковки работают с любыми двоичными данными, а не только с десятичными.

В BAL есть специальные уникальные инструкции, позволяющие за раз конвертировать двоичное число в упакованное десятичное и наоборот. Для десятичного числа в этих инструкциях всегда выделяется 8 байт, т. е. 15 цифр и знак. Однако, 32-битного регистра хватает только для представления знакового числа, соответствующего 9-значному десятичному числу, поэтому не всякое десятичное число в правильном формате BAL можно преобразовать в двоичное одной командой. Для систем Z есть расширенные инструкции для подобных преобразований.

Команды переходов в BAL отличаются тем, что они, как правило, парные – адрес перехода можно задать как явно, так и содержимым регистра – в многих других архитектурах переходы по содержимому регистра есть только для безусловных переходов. Кстати, безусловных переходов в BAL нет, они реализуются заданием всегда истинного условия, что аналогично архитектуре ARM. Условные переходы в BAL, как уже отмечалось, имеют уникальный синтаксис. Рассмотрим, например, инструкцию BT 9,address, которая означает сделать переход, если условия 0 и 3 выполнились, но условия после разных команд означают разные вещи. Например, после знакового сложения эти условия означают "результат равен 0 или произошло переполнение", а после беззнакового – "результат 0 и переноса не было или результат не 0 и перенос был". Несмотря на громоздкость и некоторую избыточность нельзя не признать, что такая система работы с условиями для переходов наверное самая гибкая из всех известных. Девятка в команде из примера используется в двоичном представлении 1001, т. е. задаёт номера бит – сама система кодировать все комбинации условий 4 битами используется и в ARM. Помимо переходов по условию в BAL есть ещё переходы по счетчику с декрементом, примерно такие же как в ассеблерах Z80, x86, 68k, PDP-11, ... Но BAL ещё имеет две совершенно уникальные инструкции для переходов, которые в зависимости от номера одного из регистров-операндов могут быть трех- или четырехадресными! В этих уникальных командах два регистра скаладываются и полученная сумма сравнивается с содержимым другого регистра и по результатам этого сравнения определяется делать переход или нет. Считается, что такие необычные инструкции удобны для работы с таблицами переходов.

Как уже отмечалось, вызов подпрограмм в BAL реализован без использования стека, через простое сохранение адреса возврата в регистре. Однако, инструкции BAL для таких вызовов, одна из которых также называется BAL, сохраняют не только адрес возврата, но и часть регистра статуса, в частности, флаги условий, длину текущей инструкции и даже маску для опциональных исключительных ситуаций, например, для целочисленного или десятичного переполнения, – об этом уже упоминалось выше. Такое необычное расширенное сохранение информации связано с тем, что счётчик команд в архитектуре мейнфреймов – это старшая часть машинного слова статуса и инструкции вызова подпрограмм механически сохраняют его старшую часть. Специальных команд для возврата из подпрограмм нет, нужно использовать обычный переход по адресу в регистре. В системах 390 в связи с переходом на 31-разрядную архитектуру появились новые команды для вызова и даже возврата из подпрограмм. Новые инструкции позволяют гибко использовать в одной программе коды, исполняющиеся в разных режимах.

Для быстрого вызова однокомандных подпрограмм в BAL есть уникальная инструкция EX, которая выполняет инструкцию по заданному адресу и переходит к следующей команде. Инструкция EX может модифицировать вызываемую инструкцию, что позволяет использовать в вызываемой инструкции любой нужный регистр или задавать параметры при массовой пересылке байт. Подобная инструкция, но более простая есть ещё в системе команд TMS9900.

Изначально в BAL не было относительных, перемещаемых переходов, таких как есть в Z80 или x86. Их добавили только в системы 390.

Несколько необычны ещё команды SPM, TM, TS, STCK и STPT. Первая из них позволяет одной командой установить все флаги операций и маску опциональных исключений. Команда TM позволяет проверить группу бит и определить три случая: все нули, все единицы, смесь из нулей и единиц. Такую проверку одной командой в других архитектурах не сделать. Однако, TM работает только с отдельными байтами в памяти. TS используется при работе с несколькими процессорами – похожая команда есть для 68k. Инструкция STCK считывает значение внешнего (!) таймера, а инструкция STPT значение внутреннего таймера, встроенного в процессорную схему. Странно, но команда STPT привилегированная, а STCK нет.

Стоит ещё упомянуть инструкции CS и CDS, которые предназначены для поддержки мультипроцессорной работы. Они реализованы для систем 370, т. е. доступны с начала 70-х. В x86 аналог CS, инструкция CMPXCHG, была реализована не ранее 1987, а аналог CDS, инструкция CMPXCHG8B, – только в 1994!

С систем 370 вводится команда самоидентификации системы STIDP, она привилегированная и не слишком информативная. Для x86 подобная команда сделана существенно мощнее. Тут можно ещё заметить, что IBM 4361 в LCM позволяет исполнить STIDP любому пользователю. Это очевидно эмуляция, срабатывающая по исключению.

Четыре адресных режима BAL задают два операнда для инструкции, пятый режим задает трехадресные команды. Однако, игнорирование части информации позволяет иметь одноадресные команды, а использование неявной информации – четырехадресные. При использовании в адресации регистр 0 имеет особую роль: он там просто игнорируется – это позволяет не учитывать базу и индекс при расчете адреса. Все инструкции BAL занимают строго 2, 4 или 6 байт. Это похоже на 68000 или PDP-11, но не на x86, VAX или ARM.

В систему 390 добавили ещё несколько режимов адресации, доведя их число до 18. Число инструкций также возросло весьма значительно, среди новых инструкций есть даже поддерживающие работу с Unicode – такого до сих пор нет для x86! Среди новых инструкций систем 390 есть и другие уникальные. В систему Z добавили ещё несколько режимов адресации, а общее число команд для современных Z весьма велико и наверное даже больше числа команд для современных x86-64!

В системах 360, 370 и 390 смещения при обращении к данным в памяти, как и в ARM, 12-разрядное, т. е. не более 4095, что не очень удобно – в больших кодах может возникнуть нехватка регистров для базы. В x86 такое смещение 16-разрядное, что, конечно, гораздо удобнее. Но в систему Z добавили поддержку адресации с 20-разрядным смещением, что, конечно, ещё лучше. Хотя, стоит отметить, что в x86-64 или даже в 68020 смещение может быть 32 битным. Как уже отмечалось, в системах до 390, как и в ARM, не было возможности использовать большие константы при работе с регистрами. Архитектура x86 здесь гораздо гибче. Поэтому при использовании ассемблера с системой 360 или 370 часто приходилось использовать литералы, псевдоконстанты, что несколько медленнее.

По быстродействию системы, совместимые с IBM/360, всегда имели неплохие показатели. Мои эксперименты с 4361-1, в частности, в проекте вычисления числа π по алгоритму-затвору, показали очень хорошие тайминги. Инструкции 4361-1 работают практически без задержек, как ARM или другие современные процессоры. Однако, из-за несколько неуклюжей системы команд, полученной в наследство из 60-х, в частности, из-за отсутствия деления на 16-разрядный делитель, результат по эффективности электроники процессора оказался на уровне 80186. Это примерно на 80% хуже результата, показанного лучшим тогда компьютером из семейства VAX, модели 785. Однако, мейнфрейм в LCM явно далеко не самый лучший среди мейнфреймов IBM доступных тогда. Здесь ещё уместно заметить, что мейнфреймы использовали каналы, специализированные процессоры, которые делали ввод-вывод очень быстрым, гораздо более быстрым, чем у большинства современных им компьютеров.

Мне студентом случилось поработать с отечественным клоном IBM/370, ЕС-1045, в 1987 через пакетный режим, а в 1989 через диалоговый. Для пакетного режима приходилось готовить перфокарты. В то время уже использовал домашний компьютер и поэтому использование архаичных перфокарт оставило не лучшее впечатление. А вот диалоговый режим был неплох, только часто ломался, при большом числе пользователей. Поэтому некоторые студенты приезжали работать к 4 утра! С тех пор больше с мейнфреймами дела иметь не получалось, только недавно решил через эмуляцию поразбираться с этой веховой для истории компьютеров технологией.

Клонирование IBM 360 было весьма популярно. Клоны делали в Англии, Германии, Японии и другими компаниями в США. В СССР это клонирование приобрело очень драматический оттенок. Ради этого клонирования произошла свёртка почти всех отечественных разработок в области ИТ, некоторые из которых были весьма перспективны. В частности была закрыта тема компьютеров Урал, о которых потом с теплотой отзывался известный компьютерщик Чарльз Симони. Закрыт был также проект БЭСМ-10, хотя машины предшествующего класса БЭСМ-6 были сравнимы с IBM 360 по быстродействию. Также ради этого клонирования сорвали почти заключенный контракт с ICL, возможно с этим контрактом британская индустрия ИТ приобрела бы новую динамику и не пришла бы в упадок. Только суперкомпьютеры Эльбрус, возможно из-за их связи с оборонной промышленностью, уцелели после "вторжения клонов", которое Дейкстра назвал величайшей победой США в холодной войне.

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

Интересно, что главный разработчик IBM 360 ушел из IBM и основал фирму Amdahl, которая более двух десятков лет специализировалась на производстве систем, совместимых с мейнфреймами IBM и при этом несколько их превосходящих по быстродействию и надежности при более низких ценах. В итоге из-за больших перемен на рынке мейнфреймов, Amdahl, как и ICL, стали частью японской корпорации Fujitsu.

Помимо компьютеров архитектуры IBM/360 существовали и другие мейнфреймы. В 60-е американские производители мейнфреймов неофициально получили звучное имя Белоснежка и семь гномов. Наверное несложно догадаться, что Белоснежкой была компания IBM. Мейнфреймы оригинальных архитектур производили и в других странах. Особо стоит упомянуть британскую архитектуру ICL 1900.

Как уже писал, мне удалось настроить рабочую конфигурацию для VM/CMS 6. Однако, обнаружилось, что редактора XEDIT в свободном доступе нет, а простой EDIT слишком своеобразен и неудобен, поэтому редактировать тексты приходится в хосте. Также обнаружилось недоступность штатной программы для переноса файлов с эмулятора терминала на мейнфрейм и обратно, что потребовало использования виртуальных перфокарт для такого переноса. Другая неприятная неожиданность обнаружилась в связи с отладкой. Команда DEBUG не поддерживает пошагового исполнения! В то время как такая возможность была даже для отладчика DDT для процессора 8080. Также удивительно, хотя и менее критично, что DEBUG не умеет делать дизассемблирование, которое часто встраивалось даже в простейшие мониторы процессоров 70-х. Под CMS на низком уровне не поддерживается перенос длинных строк и управляющий символ конца строки! Поэтому при печати из программ на ассемблере нужно форматировать строки вручную, чтобы они не пропадали за правым краем экрана, а также заботиться о заполнении финишными пробелами последней строки. Также необычно отсутствие автоматического вертикального скроллинга.

Тем, кто захочет поработать с мейнфреймами впервые, стоит иметь в виду, что мейнфреймы – это огромная экосистема, где многие привычные понятия могут иметь другую трактовку. Например, простого понятия файл там нет. Одним из ключевых атрибутов файла является размер записи, ничего подобного для файлов Linux или Microsoft Windows нет. Сами файлы различаются по методам доступа к ним и об этом писались и возможно пишутся нетонкие книги. Также необычно, что в CMS имя диска пишется в конце полного имени файла, а разделяются имя, расширение и диск пробелами, причем само имя диска называется почему-то режимом файла. Хотелось бы ещё поразбираться с многозадачной MVS, насколько знаю в СССР до неё так и не дошли.

Вообще несколько неожиданно, что некоторые известные операционные системы, которые использовались на весьма дорогих компьютерах, не поддерживали работу с каталогами файлов, что равняло их с самыми первыми и примитивными ОС для микрокомпьютеров, например, CP/M или Commodore DOS. Не случайно поэтому CMS иногда называли CP/M для мейнфреймов. Удивительно, но насколько мне известно, поддержку для каталогов в CMS так и не ввели, хотя последний выпуск системы датируется 2018. Почему-то работа с каталогами для дорогих компьютеров до 80-х поддерживалась часто плохо. Например, такой поддержки не было в DEC RT-11 и даже одна из лучших ОС для PDP-11, RSX-11, поддерживала только двухуровневые каталоги. Самая популярная IBM ОС до 2000-х была MVS (1974) и даже тут каталоги были сделаны только частично, как и в Apple MFS (1984). Хотя в Unix (1973), MS-DOS (с 1983) или даже 8-битной Apple ProDOS (1983) с этим всё было в порядке с самого начала. Самая продвинутая работа с файлами предлагалась в VAX/VMS (1977), где помимо каталогов есть даже встроенная поддержка версионирования файлов.

Интересно, что язык сценариев для CMS, MVS и некоторых других IBM ОС, REXX, в сокращенном варианте стал языком командных файлов для Commodore Amiga.

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

Динамическая демка, запущена на эмуляторе IBM 4381 в LCM, терминал 3270-3

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

Тема мейнфреймов огромна. Конечно, смог написать только небольшую часть того, что она может вместить. Буду очень признателен за уточнения и дополнительную информацию.


Cтатья опубликована на Хабре, а также переведена на английский.