Появление кода цифры в знаковом полубайте или кода знака в цифровом вызывает программное прерывание по особому случаю данных.
Немного дополню: такие данные могут получиться вследствие недопустимого перекрытия операндов команд десятичной арифметики. Вкратце, допустимые варианты определяются как если бы процессор обрабатывал десятичные числа справа налево по одному байту и сразу записывал результат. В большинстве случаев требуется, чтобы при перекрытии совпадали самые правые байты.
Именно что энергетически. А чтобы сжечь водород, полученный где-то, его нужно ещё доставить до машины, т.е. построить и обслуживать сеть водородных заправочных станций. Что, в свою очередь, невыгодно экономически.
Одни из самых сложных процедур в оптимизирующем кодогенераторе -- это поиск в программе паттернов, которые бы отображались напрямую на комбинации команд и режимов адресации в прикладном режиме. И я не сказал бы, что красивая система команд однозначно упрощает этот процесс. Приведу пример из PDP-11.
Имеется автодекрементная адресация, которая по архитектуре применима ко многим командам. Однако, чтобы задействовать этот режим адресации для генерации команд помимо MOV, требуется научить кодогенератор отыскивать очень специфичные (и редко встречающиеся) комбинации в исходном коде. Теперь, гипотетически, создадим другую, не такую красивую систему команд, в которой автодекрементую адресацию оставим только как особый случай команды MOV. Кодогенерация при этом, очевидно, упрощается: нет лишних комбинаций команд -- не нужно выявлять для них паттерны -- нет лишних проблем.
(Нетрудно заметить, что выше я просто-напросто пересказал кусок из идеологии RISC. Ну да, набор команд у них не назовешь однозначно красивым.)
Уродливость системы команд -- понятие, которое зависит от вкуса, привычек, опыта работы с ними. Если сравнивать, к примеру, с MIPS или ARM (ранними), так ЕС вполне достойно смотрится.
Только зачем нужны красивые системы команд, когда на ассемблере не пишут практически ничего? Даже операционные системы. Уже при написании IBM MVS широко использовался язык PL/S, а это середина 1970-х.
16 Мбайт памяти — это огромная величина для середины 1960-х годов, машины с таким объёмом ОП стали сколько-нибудь массово появляться «у них» лишь во второй половине 1970-х
Забавный факт: программа начальной загрузки (IPL) ранних версий OS/360 зацикливается при максимальном размере ОП 16 Мб. Происходит это потому, что определение размера ОП реализовано так: выполняется чтение через каждые 2 Кб и перехват прерывания, возникающего при выходе за доступный размер ОП. Соответственно, на 16 Мб такого прерывания не возникает.
Более поздняя версия IPL выполняет этот цикл более корректно, с проверкой верхней границы.
Насколько я помню публикации про эту технологию, основной упор делался на то, что не потребуется создавать сеть для хранения и распределения водорода (с чем до сих пор проблема): у машины в баках чистая вода.
В таком виде, как сейчас, -- показуха, безусловно, но если начать использовать отходы производства (упомянутую алюминиевую стружку) и вторсырьё, то, может, и получится кое-какая выгода. Затраты при этом будут не на производство алюминия, а на сбор сырья и на этот самый нанопорошок.
Было такое, и как раз на ЕС 1036. Делаешь себе виртуальную машину со своей любимой ОС и своими любимыми командами -- по крайней мере, по документации было всё гладко.
С практической пользой тяжелее, но в комплекте шёл пакет расширения для числовых расчетов.
ЕС 1036, 1046 и 1066 -- аналоги IBM 303x, в которых изначально присутствует функциональность расширения команд. Для первых двух читал соответствующую документацию, жаль, руки не дошли попробовать на практике.
Тут нужно иметь в виду, что младшие модели System/360 могли ещё работать эмуляторами более ранних мэйнфреймов, а для этого, возможно, и 64 Кб хватало с избытком.
PCP был стартовой системой в первых релизах OS/360, потом заменили на MFT и да, вот я смотрю минимальные требования для Starter System Release 21 -- там MFT и 128 Кб. В ОС ЕС 4.1, кажется, тоже был PCP, но в 6.1 стартером сделали MFT.
Заметим, что на модели 30 Системы 360, имевшей примерно такую же производительность, запустить OS/360 невозможно, так как «американка» не может иметь больше 64 Кбайт памяти, а OS/360 для нормальной работы требуется не менее 128 Кбайт
Первые модели System/360 работали под DOS из-за того что IBM не успела вовремя с OS/360. Версию OS для 64 Кб тоже можно было сгенерировать, в режиме PCP или MFT, как стартер. Другое дело, что эти режимы, как и сами 64 Кб памяти, быстро стали анахронизмом.
Для начала, постараюсь ввести в контекст, насколько возможно кратко.
Основная структура, с помощью которой в OS/360 выполняются операции с набором данных (НД), -- это блок DCB (Data Control Block), который располагается в области памяти программы. После открытия НД создаётся блок DEB (Data Extent Block) в системной области памяти, в который записывается информация, требующая защиты от посторонних изменений, например, границы областей диска, в которых расположен НД (extents, отсюда и название этого блока). Эта область памяти защищена нулевым ключём, т.е. изменять её содержимое может только ОС.
Небольшое отступление: если говорить про защиту системных данных применительно к OS/360, имеется в виду защита именно от несанкционированного изменения этих данных. Защита от чтения отсутствует; более того, в ряде случаев, чтобы программа получила ту или иную нужную ей информацию, требуется пройти по цепочке указателей на системные блоки, найти требуемый блок и извлечь данные из него.
Так вот, помимо всего прочего в DEB содержатся адреса т.наз. программ-аппендиксов. Это, по сути, callbacks, которые ОС вызывает в определенных ситуациях в процессе ввода-вывода. Состав и функции аппендиксов варьируются в зависимости от метода доступа. Понятно, почему требуется защищать их адреса: если программа сумеет заменить один из них, последует передача управления по этому адресу в состоянии процессора "супервизор" и с нулевым ключём защиты памяти (иными словами, в системном контексте).
Для базисного индексно-последовательного метода доступа (BISAM) и базисного прямого метода доступа (BDAM), которые работают только с дисками, была реализована дополнительно функция динамической буферизации. Что это такое: обычно требуется, чтобы область памяти для чтения данных из ВУ была выделена заранее. В случае, когда НД может содержать блоки данных разного размера, при этом приходится заранее выделять область максимальной длины, даже если она вся не потребуется. При динамический буферизации заранее ничего выделять не требуется: в ходе операции ввода ОС прочитает размер блока данных из области счёта на диске, выделит для него область памяти необходимого размера и прочитает туда блок данных.
После успешного завершения операции чтения программа может работать с прочитанным блоком данных, изменить там что-нибудь, не меняя длины, и записать его обратно на диск. После успешного завершения операции записи ОС освободит выделенную область памяти. Также можно просто освободить эту область при помощи системного вызова FREEDBUF.
Здесь я не очень понимаю, почему для такого освобождения памяти понадобился отдельный системный вызов (SVC). Например, при обычной буферизации буфер возвращается в свой пул при помощи вызова модуля из программы, не требуя для этого ни состояния супервизора, ни нулевого ключа защиты. Возможно, дело в том, что первоначально этот вызов и не планировался, но затем выяснилось, что при освобождении потребуется что-то поменять в других системных блоках. Так или иначе, это самый короткий из системных вызовов по объему кода и, на мой взгляд, носит явные следы спешки при реализации, что и повлекло за собой появление дырки в защите.
Что делает обработчик SVC FREEDBUF: он получает указатель на DCB, определяет метод доступа BISAM либо BDAM, читает адрес DEB из DCB, [здесь я отпускаю небольшое блуждание по системным структурам], читает адрес требуемого аппендикса, в зависимости от метода доступа, передаёт по управление по этому адресу и после возврата управления заканчивает обработку системного вызова.
Видите, в чём подвох? Управление в системном контексте передается "куда-то туда", не проверив предварительно подлинность переданных в системный вызов параметров! А проверить-то было очень просто: пройти по цепочке блоков DEB для данной задачи (процесса в современных ОС), сравнивать обратные адреса DCB в этих DEB с параметром и, если не совпадает ни один, непонятно ругаться, уж что-что, а это OS/360 умела.
Теперь воспользуемся этой дыркой. Пишем блок данных, который якобы DCB, но заполняем только те поля, к которым обращается SVC и подставляем адрес якобы блока DEB. Дальше поступаем аналогичным образом, пока не доберемся до адреса аппендикса, куда подставляем, разумеется, указатель на свою процедуру. Профит! ;)
Скажу ещё пару слов про NEWPSW. Прежде всего, она определяла версию ОС. Для MFT/MVT/SVS использовалась указанная дырка, а для MVS какая-то другая (с ней я не стал разбираться по причине недостаточной документации и опыта работы с MVS). Затем она вызывала FREEDBUF с указателем на фальшивый DCB. (Так совпало, что свой proof-of-concept я написал для одного метода доступа, а NEWPSW эксплуатирует другой.) Получив управление с нулевым ключём защиты, процедура находила сохранённый PSW для переключения обратно после системного вызова и заменяла в нем флаг состояния и ключ защиты памяти, сохранив старые значения. Таким образом, с помощью NEWPSW можно было, например, установить нулевой ключ защиты, что-нибудь поменять в системных блоках и вернуть ключ защиты программы. Либо установить состояние супервизора, запретить прерывания, произвести какие-то атомарные операции, снова разрешить прерывания и вернуть состояние программы.
Почти полные, я не нашел только кое-какие из модулей QSAM. А так -- начальный загрузчик, модули ядра, утилиты, ASM F, редактор связей, загрузчик, компиляторы. Ищите "ОS/360 CD" и "os360mvt.tar.gz" Я когда-то скачивал здесь, но сейчас у меня эта ссылка не открывается. В крайнем случае, поделюсь своей копией.
MODESET -- это для тех, кто не в курсе. В ОС ЕС 4.1 и 6.1 была дырка в SVC вызове FREEDBUF, доставшаяся "по наследству" от MVT. Никакого пароля она не требовала в принципе, и ещё ходила удобная "обертка" для неё в виде процедуры NEWPSW. Я не так давно изучил, как они обе работают, по исходникам MVT и дампу процедуры, могу здесь рассказать.
Совершенно верно, поэтому обсуждение продолжилось таким образом: мы не требуем работоспособности от загруженной таким образом программы. То есть достаточно, чтобы успешно завершилась аппаратная часть процедуры IPL (в реальности она микропрограммная). Иными словами, требуется, чтобы погасла индикация начальной загрузки на пульте управления ЭВМ.
Мне говорили, что ЕС-1036, ЕС-1046 и ЕС-1066 соответствуют серии IBM 303X. То есть, ЕС-1066 - это копия IBM Model 3033.
Немного дополню: такие данные могут получиться вследствие недопустимого перекрытия операндов команд десятичной арифметики. Вкратце, допустимые варианты определяются как если бы процессор обрабатывал десятичные числа справа налево по одному байту и сразу записывал результат. В большинстве случаев требуется, чтобы при перекрытии совпадали самые правые байты.
Именно что энергетически. А чтобы сжечь водород, полученный где-то, его нужно ещё доставить до машины, т.е. построить и обслуживать сеть водородных заправочных станций. Что, в свою очередь, невыгодно экономически.
Одни из самых сложных процедур в оптимизирующем кодогенераторе -- это поиск в программе паттернов, которые бы отображались напрямую на комбинации команд и режимов адресации в прикладном режиме. И я не сказал бы, что красивая система команд однозначно упрощает этот процесс. Приведу пример из PDP-11.
Имеется автодекрементная адресация, которая по архитектуре применима ко многим командам. Однако, чтобы задействовать этот режим адресации для генерации команд помимо MOV, требуется научить кодогенератор отыскивать очень специфичные (и редко встречающиеся) комбинации в исходном коде. Теперь, гипотетически, создадим другую, не такую красивую систему команд, в которой автодекрементую адресацию оставим только как особый случай команды MOV. Кодогенерация при этом, очевидно, упрощается: нет лишних комбинаций команд -- не нужно выявлять для них паттерны -- нет лишних проблем.
(Нетрудно заметить, что выше я просто-напросто пересказал кусок из идеологии RISC. Ну да, набор команд у них не назовешь однозначно красивым.)
Уродливость системы команд -- понятие, которое зависит от вкуса, привычек, опыта работы с ними. Если сравнивать, к примеру, с MIPS или ARM (ранними), так ЕС вполне достойно смотрится.
Только зачем нужны красивые системы команд, когда на ассемблере не пишут практически ничего? Даже операционные системы. Уже при написании IBM MVS широко использовался язык PL/S, а это середина 1970-х.
Я встречал упоминание о ещё двух вариантах:
Срабатывание схем аппаратного контроля может сразу перевести ЦП в останов, а не вызывать соответствующее прерывание.
Некорректное PSW программных прерываний на некоторых моделях также может перевести ЦП в останов.
Забавный факт: программа начальной загрузки (IPL) ранних версий OS/360 зацикливается при максимальном размере ОП 16 Мб. Происходит это потому, что определение размера ОП реализовано так: выполняется чтение через каждые 2 Кб и перехват прерывания, возникающего при выходе за доступный размер ОП. Соответственно, на 16 Мб такого прерывания не возникает.
Более поздняя версия IPL выполняет этот цикл более корректно, с проверкой верхней границы.
Насколько я помню публикации про эту технологию, основной упор делался на то, что не потребуется создавать сеть для хранения и распределения водорода (с чем до сих пор проблема): у машины в баках чистая вода.
В таком виде, как сейчас, -- показуха, безусловно, но если начать использовать отходы производства (упомянутую алюминиевую стружку) и вторсырьё, то, может, и получится кое-какая выгода. Затраты при этом будут не на производство алюминия, а на сбор сырья и на этот самый нанопорошок.
В очередной раз сошлюсь на мой любимый сайт со сканами старых документов, вот небольшая подборка:
PL/1 для System/360
PL/1 для System/370
Добавлю сюда кое-какую документацию по микропрограммированию от IBM
Model 25 microprogramm listing
Model 30 microprogramming language
Introduction to microprogramming
Было такое, и как раз на ЕС 1036. Делаешь себе виртуальную машину со своей любимой ОС и своими любимыми командами -- по крайней мере, по документации было всё гладко.
С практической пользой тяжелее, но в комплекте шёл пакет расширения для числовых расчетов.
ЕС 1036, 1046 и 1066 -- аналоги IBM 303x, в которых изначально присутствует функциональность расширения команд. Для первых двух читал соответствующую документацию, жаль, руки не дошли попробовать на практике.
Тут нужно иметь в виду, что младшие модели System/360 могли ещё работать эмуляторами более ранних мэйнфреймов, а для этого, возможно, и 64 Кб хватало с избытком.
PCP был стартовой системой в первых релизах OS/360, потом заменили на MFT и да, вот я смотрю минимальные требования для Starter System Release 21 -- там MFT и 128 Кб. В ОС ЕС 4.1, кажется, тоже был PCP, но в 6.1 стартером сделали MFT.
Первые модели System/360 работали под DOS из-за того что IBM не успела вовремя с OS/360. Версию OS для 64 Кб тоже можно было сгенерировать, в режиме PCP или MFT, как стартер. Другое дело, что эти режимы, как и сами 64 Кб памяти, быстро стали анахронизмом.
Для начала, постараюсь ввести в контекст, насколько возможно кратко.
Основная структура, с помощью которой в OS/360 выполняются операции с набором данных (НД), -- это блок DCB (Data Control Block), который располагается в области памяти программы. После открытия НД создаётся блок DEB (Data Extent Block) в системной области памяти, в который записывается информация, требующая защиты от посторонних изменений, например, границы областей диска, в которых расположен НД (extents, отсюда и название этого блока). Эта область памяти защищена нулевым ключём, т.е. изменять её содержимое может только ОС.
Небольшое отступление: если говорить про защиту системных данных применительно к OS/360, имеется в виду защита именно от несанкционированного изменения этих данных. Защита от чтения отсутствует; более того, в ряде случаев, чтобы программа получила ту или иную нужную ей информацию, требуется пройти по цепочке указателей на системные блоки, найти требуемый блок и извлечь данные из него.
Так вот, помимо всего прочего в DEB содержатся адреса т.наз. программ-аппендиксов. Это, по сути, callbacks, которые ОС вызывает в определенных ситуациях в процессе ввода-вывода. Состав и функции аппендиксов варьируются в зависимости от метода доступа. Понятно, почему требуется защищать их адреса: если программа сумеет заменить один из них, последует передача управления по этому адресу в состоянии процессора "супервизор" и с нулевым ключём защиты памяти (иными словами, в системном контексте).
Для базисного индексно-последовательного метода доступа (BISAM) и базисного прямого метода доступа (BDAM), которые работают только с дисками, была реализована дополнительно функция динамической буферизации. Что это такое: обычно требуется, чтобы область памяти для чтения данных из ВУ была выделена заранее. В случае, когда НД может содержать блоки данных разного размера, при этом приходится заранее выделять область максимальной длины, даже если она вся не потребуется. При динамический буферизации заранее ничего выделять не требуется: в ходе операции ввода ОС прочитает размер блока данных из области счёта на диске, выделит для него область памяти необходимого размера и прочитает туда блок данных.
После успешного завершения операции чтения программа может работать с прочитанным блоком данных, изменить там что-нибудь, не меняя длины, и записать его обратно на диск. После успешного завершения операции записи ОС освободит выделенную область памяти. Также можно просто освободить эту область при помощи системного вызова FREEDBUF.
Здесь я не очень понимаю, почему для такого освобождения памяти понадобился отдельный системный вызов (SVC). Например, при обычной буферизации буфер возвращается в свой пул при помощи вызова модуля из программы, не требуя для этого ни состояния супервизора, ни нулевого ключа защиты. Возможно, дело в том, что первоначально этот вызов и не планировался, но затем выяснилось, что при освобождении потребуется что-то поменять в других системных блоках. Так или иначе, это самый короткий из системных вызовов по объему кода и, на мой взгляд, носит явные следы спешки при реализации, что и повлекло за собой появление дырки в защите.
Что делает обработчик SVC FREEDBUF: он получает указатель на DCB, определяет метод доступа BISAM либо BDAM, читает адрес DEB из DCB, [здесь я отпускаю небольшое блуждание по системным структурам], читает адрес требуемого аппендикса, в зависимости от метода доступа, передаёт по управление по этому адресу и после возврата управления заканчивает обработку системного вызова.
Видите, в чём подвох? Управление в системном контексте передается "куда-то туда", не проверив предварительно подлинность переданных в системный вызов параметров! А проверить-то было очень просто: пройти по цепочке блоков DEB для данной задачи (процесса в современных ОС), сравнивать обратные адреса DCB в этих DEB с параметром и, если не совпадает ни один, непонятно ругаться, уж что-что, а это OS/360 умела.
Теперь воспользуемся этой дыркой. Пишем блок данных, который якобы DCB, но заполняем только те поля, к которым обращается SVC и подставляем адрес якобы блока DEB. Дальше поступаем аналогичным образом, пока не доберемся до адреса аппендикса, куда подставляем, разумеется, указатель на свою процедуру. Профит! ;)
Скажу ещё пару слов про NEWPSW. Прежде всего, она определяла версию ОС. Для MFT/MVT/SVS использовалась указанная дырка, а для MVS какая-то другая (с ней я не стал разбираться по причине недостаточной документации и опыта работы с MVS). Затем она вызывала FREEDBUF с указателем на фальшивый DCB. (Так совпало, что свой proof-of-concept я написал для одного метода доступа, а NEWPSW эксплуатирует другой.) Получив управление с нулевым ключём защиты, процедура находила сохранённый PSW для переключения обратно после системного вызова и заменяла в нем флаг состояния и ключ защиты памяти, сохранив старые значения. Таким образом, с помощью NEWPSW можно было, например, установить нулевой ключ защиты, что-нибудь поменять в системных блоках и вернуть ключ защиты программы. Либо установить состояние супервизора, запретить прерывания, произвести какие-то атомарные операции, снова разрешить прерывания и вернуть состояние программы.
Почти полные, я не нашел только кое-какие из модулей QSAM. А так -- начальный загрузчик, модули ядра, утилиты, ASM F, редактор связей, загрузчик, компиляторы. Ищите "ОS/360 CD" и "os360mvt.tar.gz" Я когда-то скачивал здесь, но сейчас у меня эта ссылка не открывается. В крайнем случае, поделюсь своей копией.
MODESET -- это для тех, кто не в курсе. В ОС ЕС 4.1 и 6.1 была дырка в SVC вызове FREEDBUF, доставшаяся "по наследству" от MVT. Никакого пароля она не требовала в принципе, и ещё ходила удобная "обертка" для неё в виде процедуры NEWPSW. Я не так давно изучил, как они обе работают, по исходникам MVT и дампу процедуры, могу здесь рассказать.
Совершенно верно, поэтому обсуждение продолжилось таким образом: мы не требуем работоспособности от загруженной таким образом программы. То есть достаточно, чтобы успешно завершилась аппаратная часть процедуры IPL (в реальности она микропрограммная). Иными словами, требуется, чтобы погасла индикация начальной загрузки на пульте управления ЭВМ.