Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works
Anything · Lazarus or Delphi
Random projectRandom project

dispak-tools

Various tools for OS DISPAK, disassembled/decompiled.

View on GitHub

Member rating

No ratings yet.

Sign in to rate this project.

README

dispak-tools

Various tools for OS DISPAK for BESM-6, disassembled/decompiled.

  • compiler/ — the improved Pascal compiler mypas.b6, its libraries and tests;
  • runtime/ — the recovered NEWPASC runtime libraries, the volume 4001 corpus and its analysis;
  • programs/ — the recovered programs, one directory each, with their builders;
  • py/ — the Python modules the scripts share: paths.py names every part of the project, build.py builds and checks the runtime libraries, regress.py runs every build, fixpoint.py checks a compiler change;
  • tools/ — disbesm6, dtran, buildimg.sh and the other C, shell and Perl tools (make -C tools disbesm6);
  • build/ — generated output, not tracked;
  • arfa/ — АРФА; the root holds the sample sources and decks.

Pascal runtime recovery

runtime/README.md describes the Pascal image corpus extracted from volume 4001, its analysis, and four recovered Madlen runtime libraries. Compile and run a new program with python3 py/build.py run program.pas; use python3 py/build.py check for the word comparisons and emulator checks.

MARK3

Утилита для разметки лент ЕС ЭВМ на СВС (Э1-К2) путем прямого доступа к ПВВ. Исходные тексты и сборщик, дающий тот же код, что mark3.bin, — в programs/mark3.

ПАК

Программа печати состояния ОС (паспорта задач, очереди, устройства). Две редакции (тома 2053/2048/2248 и 2113) восстановлены и пересобираются побайтово — в programs/pak.

Паскаль-компилятор

Исходный текст компилятора, библиотеки и тесты лежат в compiler/. Проверка изменения mypas.b6: python3 py/fixpoint.py.

По сравнению с базовой версией компилятора в составе МС "Дубна" или "Монитор-80", внесены следующие изменения, повторяющие изменения в компиляторе, использовавшемся для разработки кросс-системы программирования Э1-КБ:

  • неиспользуемые байты в строковых константах - нулевые (а не пробелы в коде ISO).
  • исправлена ошибка, вызывающая добавление лишнего слова, если длина строковой константы кратна 6 байтам.
  • избегается избыточная команда чтения сразу после записи (исключая, разумеется, магазинную запись) по тому же адресу в том же линейном участке.
  • опция (*=O-*) отключает предыдущий пункт: чтение после записи сохраняется, как в программах, оттранслированных исходным компилятором (например, COMP с тома 4001, см. comp.pas). По умолчанию (*=O+*). Под (*=O-*) все константы, как и в исходном компиляторе, хранятся в одной таблице, включая повторы из-за нетранзитивного сравнения ALFA (см. runtime/monitr).
  • реализована конструкция besm(константа : L-выражение), позволяющая ссылаться на переменные и элементы массивов или структур во вставках машинного кода. Например, оператор besm(0 : L-выражение); эквивалентен оператору L-выражение := ; (присваивание сумматора).
  • реализовано номинальное преобразование типов R-выражений с помощью конструкции тип(выражение). Первоначальный тип выражения должен быть однословным.
  • реализовано указание абсолютных адресов для переменных с помощью конструкции var переменная [ адрес ] : тип; Адреса обычных переменных в верхнем банке 74000B–77777B кодируются как абсолютные, без ошибочной ссылки на таблицу внешних символов; внешние файлы сохраняют свою адресацию.
  • в besm можно записывать несколько машинных команд через запятую, например besm(100000B : x, 150000B : y, 0 : z);. Числовой операнд VTM больше 40000B передаётся через абсолютный символ, чтобы загрузчик не релокировал его как адрес кода: например, besm(16471717B) сохраняет команду 3,VTM,71717B из BOX.
  • код для инициализации переменных типа файл главной программы вставляется не в самое начало объектного модуля, а непосредственно перед началом главной программы.
  • строковые константы, обрамленные двойными кавычками, всегда записываются в кодировке КОИ-8 (как при (*=A4*)), независимо от режима A. Внутри такой константы апостроф – обычный символ, а двойная кавычка удваивается.
  • соглашение о связях внешних процедур ASSEMBLER (procedure p(...); assembler;): все фактические параметры, кроме последнего, засылаются в магазин; последний остается на сумматоре (однословные параметры-значения – значением, остальные – адресом), без заголовка кадра; вызов – пв p(13). Процедура сама снимает параметры с магазина и возвращается по 13, uj,; результат функции – на сумматоре. Процедура снимает с магазина n-1 параметров, сохраняет регистры 1–7; регистр 8 восстанавливает вызывающий код. Поэтому, как и после вызова процедур FORTRAN, регистры кадров объемлющих уровней после вызова не восстанавливаются.
  • в режиме (*=Y+*), где разделы описаний могут повторяться, параметр программы (внешний массив, например program p(input, output, TTIO);) можно описать в разделе var, идущем после описаний процедур: наличие описаний всех параметров проверяется в конце всей части описаний, а не первого раздела var. Внешнее имя (*TTIO*) заводится в таблице внешних символов в точке описания, что определяет порядок загрузки модулей (так устроен COMP, см. comp.pas).
  • в режиме (*=C-*) (отмена проверки типов) фактическим параметром-переменной может быть константа: передается адрес ее слова в таблице констант (так передавал константы компилятор, которым оттранслирован АСС3 с тома 4001, и тест compiler/tests/varconst.pas). По умолчанию (*=C+*).
  • режим (*=W+*) дает код, как в АСС3 с тома 4001 (тест compiler/tests/unrollcopy.pas): присваивание объекта длиной 2 или 3 слова транслируется парами сч/зп без цикла, а конструктор множества без константных элементов (например, [i]) не объединяется с пустым множеством (счм []; или), а адрес глобальной переменной формируется как мода off(М1); уиа (Мk), а не как адрес P/1D+off, так что код не зависит от размещения P/1D (так устроены оверлеи АСС3). Значение сравнения = или <> скаляров и множеств вычисляется без переходов (нтж b; счм 025(М1); рзб (М17); чед, для = еще нтж 8(М1)), а значение сравнения целых <, >, <=, >= — как знак разности (вч b; и [7]; чед, при отрицании еще нтж 8(М1)), а значение c in s с константой c — как число единиц выделенного разряда (и [c]; чед), кроме аргумента ord; тест compiler/tests/zerotest.pas. Сдвигать функцией shift(x, n) можно любое однословное значение (например, множество), результат имеет тип x, а целое, сдвинутое вправо или на переменную величину, объединяется с целым 0 (или 0), так что набор разрядов становится целым (тест compiler/tests/wshift.pas). По умолчанию (*=W-*), как в исходном компиляторе.
  • shift(x, n) на переменную величину n транслируется как мод n; сда 64, как в старом компиляторе (вызывавшейся прежде процедуры P/II в библиотеке нет); тест compiler/tests/shift.pas.
  • в разделе .data значением может быть строковая константа длиннее 6 символов: она занимает все свои слова (с повторителем :n — каждое повторение), например msg[1] := 'ОШИБКА ПРИ ЧТЕНИИ'; для packed array [1..18] of char; тест compiler/tests/datastr.pas. Прежде допускались только однословные константы.
  • команда длинного формата в besm(...) с адресом не меньше 040000 (например, besm(3076000B), то есть пб 76000) сохраняет адрес: прежде он считался ссылкой на внешний символ и обнулялся загрузчиком; так было только для уиа (см. programs/arap); тест compiler/tests/besmlong.pas.
  • перед вызовом процедур FORTRAN ставится ржа 6 (а не ржа 2), как в программах, оттранслированных компилятором кросс-системы.
  • умножение целого на константу 2k (k > 0, константа – любой из сомножителей) при любом режиме M транслируется прибавлением k к порядку: ржа 0; слпа 64+k; ржа 7; сл 9(М1), без умножения и без константы в пуле (так делал компилятор кросс-системы, см. mark3.bin). Результат верен и для отрицательных сомножителей.
  • деление целого на константу 2k (x div 2**k, при любом режиме M) транслируется вычитанием k из порядка: вчпа 64+k; сл 9(М1) (как в ПАК с тома 2113, см. programs/pak), а не умножением на обратную константу. Частное округляется вниз и согласовано с x mod 2**k (маска): x = (x div 2**k) * 2**k + x mod 2**k; прежде точное деление отрицательного числа давало частное на 1 меньше. x div 1 больше не дает NO INTEGER.