RUЭВМ
Вы хотите отреагировать на этот пост ? Создайте аккаунт всего в несколько кликов или войдите на форум.
Апрель 2024
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
2930     

Календарь Календарь

Последние темы
» Вити больше нет!
автор bug19 Пн Фев 20 2023, 19:54

» Собираем оригинальный Орион 128
автор bug19 Пн Фев 20 2023, 19:47

» Проблема плющеного экрана ОРИОНА
автор kanzler Пн Ноя 28 2022, 12:05

» Орион 128 и его клоны возрождение 2019-2022 год
автор kanzler Пн Ноя 28 2022, 12:03

» Электроника КР-04. Информация, документы, фото.
автор kanzler Пн Ноя 28 2022, 12:02

» Новости форума
автор kanzler Пн Ноя 28 2022, 11:52

» Орион-128 НГМД запуск 2021 года
автор matrixplus Сб Сен 10 2022, 17:36

» ПЗУ F800 для РК86
автор ведущий_специалист Сб Сен 10 2022, 10:37

» Микропроцессорная лаборатория "Микролаб К580ИК80", УМК-80, УМПК-80 и др.
автор Электротехник Вт Июл 26 2022, 19:33

» Орион-128 SD карта в Орионе
автор matrixplus Чт Июн 02 2022, 09:00

» 7 Мая. День Радио!
автор Viktor2312 Чт Май 12 2022, 10:58

» Серия: Массовая радио библиотека. МРБ
автор Viktor2312 Ср Май 11 2022, 12:17

» Полезные книги
автор Viktor2312 Пн Май 09 2022, 15:07

» Орион 128 Стандарты портов и системной шины Х2
автор matrixplus Вс Май 08 2022, 23:08

» Орион-128 и Орион ПРО еще раз про блоки питания
автор matrixplus Вс Май 08 2022, 19:09

» Орион-128 Программаторы
автор matrixplus Вс Май 08 2022, 19:02

» Орион ПРО история сборки 2021 до 2022
автор matrixplus Вс Май 08 2022, 18:47

» Анонсы монет (New coin).
автор Viktor2312 Сб Май 07 2022, 23:11

» Хочу свой усилок для квартиры собрать не спеша
автор Viktor2312 Сб Май 07 2022, 19:33

» Амфитон 25у-002С
автор Viktor2312 Сб Май 07 2022, 09:38

» Майнер: T-Rex
автор Viktor2312 Вс Май 01 2022, 09:12

» GoWin. Изучение документации. SUG100-2.6E_Gowin Software User Guide. Среда разработки EDA.
автор Viktor2312 Пн Апр 25 2022, 01:01

» GoWin. Изучение документации. UG286-1.9.1E Gowin Clock User Guide.
автор Viktor2312 Сб Апр 23 2022, 18:22

» GoWin. Documentation Database. Device. GW2A.
автор Viktor2312 Ср Апр 20 2022, 14:08

» GOWIN AEC IP
автор Viktor2312 Ср Апр 20 2022, 12:08

Самые активные пользователи за месяц
Нет пользователей

Поиск
 
 

Результаты :
 


Rechercher Расширенный поиск


Использование ЯВУ для разработки программ для РК86

Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Использование ЯВУ для разработки программ для РК86

Сообщение  barsik Чт Сен 07 2017, 15:07

1
Общеизвестно, что программирование на ассемблере очень неэффективно. В книге Эльфринга написано, что хороший программист в среднем за рабочий день создает всего 100 строк исходного текста (а программа объёмом в 14 кб имеет исходник в 7000 строк ассемблера). Понятно, что набрать в редакторе за один день можно и тысячи строк, только проблема в том, что это точно не будет работать.

Т.к программирование на ассемблере очень чревато ошибками, то требуется обязательно тестировать любую процедуру написанную на ассемблере. И в случае ошибки, приходится выяснять проблему путём долгой и кропотливой возни с отладчиком. Так что неэффективность ассемблера объясняется вовсе не сложностью хранить в голове конструкции, форматы данных, адреса и т.п (это-то как раз не проблема), а главным образом в том, что очень легко ошибиться, а найти потом эти ошибки сложно.

Поэтому и придумали языки высокого уровня (ЯВУ), т.к ЯВУ даже древний, намного более продуктивен, чем ассемблер. Впрочем, не надо обольщаться. Как написано в предисловии книги У.Морера, почти все коммерчески успешные программы для 8-ми разрядок были написаны именно на ассемблере, а на ЯВУ не было написано вообще ничего (кроме банковских программ на Коболе). Проблема в том, что 8-ми разрядки имеют мало памяти, а объём кода из под компилятора очень быстро нарастает с ростом сложности программы. Объём кода программы на ЯВУ в 4-8 раз больше, а скорость прогона во столько же ниже по сравнению с ассемблером.

Стоит заметить, что в литературе встречается утверждение, что есть один более эффективный, вероятно самый низкоуровневый ЯВУ - PL/M. Про который его автор Гарри Килэлл утверждал, что для больших программ он генерит даже более эффективный код, чем на ассемблере. Теоретически это невозможно, но реальные программы на ассемблере пишут живые люди, которые пишут не идеально (применяя повторные куски кода и неоптимальные алгоритмы), потому похоже, что автор PL/M был прав. Но для меня пока это остаётся непроверенным слухом и городской легендой, т.к CP/M-версии компилятора нет.

Но даже для критичных по скорости и объёму кода программ выход есть - это использование ЯВУ с заменой части процедур на ассемблер. Это удобно в BDS Си (не Aztec), а также в большинстве других ЯВУ (где используется линковка). Даже широко презираемый программистами бейсик имеет компиляторы с линковщиком, что позволяет встраивать в программу бейсика куски написанные на ассемблере без всяких ухищрений свойственных интерпретатору (за счёт загрузки кодов из операторов DATA).

Впрочем уверен, что для несложных по логике и графике программ, уровня XONIX, PACMAN даже возможностей голого ЯВУ без вкраплений ассемблера достаточно. Например, первый PACMAN для 8-ми разрядки вообще был написан на интерпретаторе бейсика, а это уж какая тормозятина.

Надеюсь, что вышенаписанного достаточно, чтобы показать, что использование ЯВУ при разработке ПО для РК86 имеет смысл. Но как это сделать, ведь компиляторы работают в CP/M и генерируют код рассчитанный для работы в CP/M? А нам требуется поиметь на выходе программу пригодную для запуска из среды монитора РК.

Из-за отсутствия в базовом РК86 входов BDOS и BIOS, в программе нельзя использовать стандартные функции ввода/вывода. Понятно, что программе рассчитанной для РК без CP/M не следует лезть к дискете. Но даже и без этого, т.к программы CP/M для ввода/вывода используют BDOS и BIOS, то странслированная традиционно программа всё-равно работать не будет.

Для решения проблемы есть несколько вариантов. Во-первых, можно сделать эмуляцию CP/M, а именно пристроить к программе эмулятор BDOS/BIOS. Во-вторых, можно переписать в компиляторе некоторые процедуры низкого уровня в RUN-тайм библиотеке. Исходник RUN-тайм библитеки у некоторых компиляторов (например BDS Си) включён в дистрибутив и их изменить несложно (переадресовав вызовы консольных функций BDOS на входы F812, F803 и F809).

В третьих, можно написать процедуры и функции на ассемблере делающие вызовы ПЗУ F800. Проще всего это делается в компиляторах, где есть оператор INLINE (или #ASM...#ENDASM). Компиляторы Паскаль МТ+, AZTEC и BDS Си это свойство имеют. Тогда тратится всего 3 минуты, чтобы вставив маш.коды команды CALL на стандартные входы ПЗУ, получить процедуры и функции для вызова из Паскаля подпрограмм ПЗУ РК86.

Т.е используя INLINE-ассемблер пишутся интерфейсные функции типа CONOUT, GETKEY, GOTOXY, MSSG, что и позволяет делать интерфейс с железом РК, не используя стандартные функции ЯВУ. Если же в ЯВУ нет встроенного ассемблера, можно это сделать внешними процедурами на ассемблере.

Эмулятор BDOS, BIOS это единственное решение для тех ЯВУ, где нет ассемблера и невозможно что-то изменить в RUN-тайм библиотеке. Программа транслируется для CP/M, используя стандартные процедуры. А затем к коду программы подключается блок эмулятора BDOS и BIOS, это всего 0.5 кб кода. Например, на Паскале МТ+ это сделать легко, т.к код странслированной программы в начале специально имеет 16 NOP-ов, куда пользователь может вставить свой код инициализации. Как выглядит эмулятор BDOS/BIOS можно посмотреть на программе DDT, что я адаптировал для РК86 от CP/M.

СИ даёт больше возможностей, генерит несколько более компактный и скоростной код, хотя Паскаль легче в освоении и симпатичен для тех, кто ранее имел дело с бейсиком. Тут для Z80 выбор есть, а вот для КР580 выбора практически нет. Есть всего три Паскаля выдающих код КР580, из них два - МТ Plus и JRT хорошо документированы. МТ+ довольно эффективный, хотя слышал мнение, что он даёт код более объёмный, чем BDS Си. Зато Паскаль проще и его учат в школе и ВУЗ-е. В любом случае код от компилятора прогоняется на порядок быстрее, чем в бейсик интерпретаторе.

В 80-тые годы, в эпоху популярности РК, ЯВУ были недоступны, но меня удивляет почему сейчас, когда всё это доступно и есть живые любители РК86, никто не начал использовать ЯВУ. Смысл этого поста в том, чтобы убедить фанатов РК, что даже с небольшими трудозатратами можно писать игры. Т.к написание игр для РК на ассемблере более трудоёмко, то использование ЯВУ это выход. Можно писать новые игры. Но есть смысл даже в переписывании старых игр РК86, потому что теперь можно использовать цвет (оцветить старые игры) и путём использования специального фонта с фигурками, состоящими из тайлов (например в матрице 2*2 знакоместа), получить визуально на экране полноценную графику, причём не имея скоростных ограничений, как это на графических ЭВМ, которые тормозят.

Надеюсь, что через полгода мне и самому удастся продолжить эту тему и показать, как можно написать XONIX или PACMAN на ЯВУ. Мучает только проблема выбора - Си, Паскаль, бейсик-компилятор или PL/M. Каждый из них имеет свои преимущества.

И нужен компилятор с хорошей документацией. Пока нашёл документацию по бейсикам-компиляторам CBASIC и BASCOM, Паскалю МТ+ и Aztec и BDS Си и, читая пытаюсь что-нибудь вспомнить, т.к уже ничего не помню и по уровню знаний равен полному чайнику в программировании на ЯВУ.

На первый взгляд кажется, что даже на бейсике компиляторе можно бы написать вполне приличное ПО для РК86, а скорость разработки будет даже выше. Но пока с бейсиком-компилятором некоторая неясность, - надо разобраться как делать ПО, работающее без ДОС, т.к обычно бейсики компиляторы генерируют не машинный, а промежуточный код и используют BRUN-модуль, из-за чего без ДОС работать вообще не могут, исходников RUN-тайм библиотеки нет и базовые процедуры не изменить. Кажется всё-же можно компоновать одномодульные CP/M-программы, и тогда за счёт вызова USR-подпрограмм можно выкрутиться, т.е делать программы на бейсике не использующие вызовов BDOS или BIOS CP/M.

Но вы не ждите когда я что-нибудь "рожу", вы можете легко сами сделать то же самое и начать делать игры для РК86 на каком нибудь ЯВУ. Для этого достаточно найти какую-нибудь среду, где работает любой из перечисленных выше компиляторов ЯВУ для CP/M. В простейшем случае - это эмулятор какого-нибудь компьютера, где есть CP/M и можно прогонять CP/M компиляторы. И проверять результирующий код для начала удобнее в эмуляторе РК86, т.к обычно очень хлопотно пересылать коды из IBM PC на реал.

Для использования корректных CP/M-программ, таких как большинство компиляторов, удобнее всего пользоваться резидентными эмуляторами CP/M, типа 22NICE. Они позволяют запускать программы CP/M в MSDOS и Windows XP так, как будто это программы для IBM PC (в более новых Windows - нет, там нет поддержки MSDOS). Благодаря BAT-файлам получается очень удобно, хлоп по кнопке и всё транслируется и через секунду Вы уже в эмуляторе, проверяете результат. Такого удобства никогда не получить используя компиляцию на реальной ЭВМ (даже если бы в РК для этого хватало ОЗУ и скорости).

Кстати, собственно нехватка ОЗУ в РК уже не стоит остро, как это было в 80-тые, т.к даже для программы написанной на ЯВУ объёма 29 кб для загрузки кода и, для РК с совместимым расширением ОЗУ, ещё 15 кб в области 8400...BFFF) под буфер данных вполне достаточно. В случае необходимости  несложно доработать РК, чтобы иметь сплошное ОЗУ в 48К. Кстати, раз уж сплошные 48К по принципу Микроши получить легко, то почему нет? Например, CP/M-Нортон написанный на BDS Си занимает 32 кб. А игры написанные на ЯВУ и содержащие много лабиринтов уж точно превысят размер в 29 кб.

Интересно, что загрузка программ размера большего чем 29 кб с магнитофона в системе, где ОЗУ расширено в окне A000...BFFF (тогда ОЗУ занимает два несмежные участка), должна происходить в три этапа. Для этого пишется стартёр, автоматически перехватывающий управление при загрузке по I, который и грузит два блока кодов в ОЗУ A000...BFFF и 0...7600. Стартёр перехватывает управление (за счёт загрузки кода в стек), выводит на 4 секунды мигающую надпись "Do not stop tape" и затем два блока считываются и стартуют.

Естественно, если ОЗУ сплошное в 48 кб, то загрузка программы размером более 29 кб и одним сплошным куском не проблема. При такой уже несовместимой по порту клавиатуры доработки, удобнее использовать двухрежимный монитор, который работает в двух режимах на 32 кб и на 48 кб (отличие прошивок только в адресе ППА клавиатуры и адресе экрана). Тогда в режиме 48 кб можно грузить большие программы под 45 кб одним блоком. Физически это достигается тем, что на РФ2 с ROM-BIOS напаивается второе ПЗУ РФ2. И, если в момент нажатия кнопки сброс удерживается клавиша <УС>, то стартует монитор на 48 кб. Это удобно, не требуется доп.управление и сохраняется совместимость. Два компьютера в одном флаконе.

Так как, в качестве языка программирования очень перспективен PL/M, прилагаю ссылку на подборку материалов по языку PL/M и по языку PL1 для программирования для КР580.

Для PL1 есть версия компилятора для CP/M. Хотя PL/M похож на PL1, про его эффективность ничего неизвестно. Точнее некоторые, начитавшись Википедии, PL1 ругают, но сомневаюсь, что для 8-ми разрядки стали бы писать неэффективный компилятор. Возможно он такой же тормозной как Си или Паскаль, но скорее всего, т.к основы языка те же, он также эффективен, как и PL/M. В любом случае для начала освоения PL/M он тоже годится, т.к в нём можно использовать только те операторы, что есть и в PL/M.


Последний раз редактировалось: barsik (Пн Ноя 05 2018, 02:18), всего редактировалось 2 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Паскаль для разработки программ РК86

Сообщение  barsik Пт Апр 27 2018, 14:46

2
Дилемма Паскаль или Си отравила жизнь многим дилетантам в программировании. В 90-тые, пытаясь освоить программирование, я постоянно разрывался, занимался и тем и этим. В итоге метания между компилятором BASIC-а, Си и Паскалем сильно мне вредили. В итоге неэффективно потрачено время. Лучше не повторять этой ошибки и строго заниматься только СИ или только Паскалем.

После долгого обдумывания, для программирования для РК86 выбираю Паскаль. Хотя на Си я программировал больше, и Си считается лучшим. Пусть Си популярнее, а компиляторы Си для 8-ми разрядки эффективнее и возможности Си выше, но для меня бОльшее значение имеет приятность программирования, да и бОльшая лёгкость в освоении тоже важна, т.к я очень давно не программировал и из-за возраста "входное сопротивление" моего мозга резко повысилось. Мне важнее более приятный процесс, чем более качественный результат.

Далее необходимо сделать выбор компилятора. Для КР580 есть 4 альтернативы. Это три компилятора для CP/M и родной компилятор для РК86 (работающий без ДОС). Для начала, чтобы убедиться в их работоспособности попробовал написать Hello World на всех этих компиляторах. Эти компиляторы я сложил здесь. Если у Вас есть другой Паскаль, что компилирует в код для КР580, дайте знать. Вроде бы были популярны PascalP и USCD Pascal, оба использующие P-код, но пока их не нашёл.

Родной компилятор Паскаля для РК86 у меня есть, но сейчас он недоступен, т.к остался на архивных дискетах RK-DOS, которые не считать на PC. Это не важно, т.к этот компилятор сразу-же отпадает по следующим причинам.

Для РК86 есть Паскаль от Микроши (а также Best-Си и Фортран). Но этот Паскаль не полноценный компилятор, т.к вместо маленькой RUN-тайм библиотеки, использует в качестве неё сам компилятор, отчего объём странслированной программы увеличивается не на 1-2 кб библиотеки времени исполнения, а разбухает аж на целых 16 кб кода всего компилятора. Что делает этот Паскаль пригодным лишь для знакомства с Паскалем.

Трансляция происходит сначала в текст на ассемблере, который затем ассемблируется ассемблером МИКРОН. Это приводит к тому, что в ОЗУ РК должны одновременно умещаться: текстов редактор (2 кб), компилятор Паскаля, компилятор ассемблера (2 кб), исходный текст на Паскале, промежуточный текст на ассемблере и результирующий объектный код странслированной программы. С учётом мизерности размера ОЗУ в РК максимальный размер программы ограничен в 200 строк Паскаля. То же самое относится и РК-компилятору Best-Си, хотя на ОРИОНЕ на нём писали игры.

На других отечественных компьютерах с бОльшим ОЗУ (Партнёр и Вектор) с успехом использовался ЛС-паскаль, который использует P-код. Но увы, его версий для РК или ОРИОНА не встречал.

Один из трёх CP/M компиляторов Паскаля для КР580 также отпал, т.к мне не удалось странслировать на нём Hello World. Разобраться не смог, т.к к этому Паскалю нет никакой документации.

Из 4-х попробованных версий JRT-паскаля одна (3.0) оказалась дохлой. JRT-паскаль оказался очень эфективным по объёму кода (код Hello World всего 32 байта) и документация к нему хорошая. Но увы, этот компилятор транслирует не в COM-файл, а в INT-файл, для запуска которого используется программа EXEC.COM размером в 24 кб. Это не годится не только из-за огромного размера кода, а то, что без CP/M программа EXEC не может загрузить INT-файл и следовательно это не удастся использовать на РК86 без CP/M. Жалко, что JR-Паскаль не годится, т.к в нём есть многие вещи, что отсутствуют в МТ+.

В итоге, как ни крути, остался всего один компилятор Паскаля, который позволяет транслировать программы для РК86. Это Паскаль МТ+. Дополнительным плюсом МТ+ является наличие отладчика, возможность анализа ассемблерного кода полученного от каждого оператора Паскаля и возможность трансляции кода на любые адреса и для ПЗУ. Hello World транслируется в программу объёмом в 4 кб (использование ключа $K позволяет исключить ненужные стандартные операторы из кода, что сокращает объём, но пока в этом не разбирался).).

Есть 3 версии компилятора MT+. Есть версия 5.5 от фирмы MicroSystems и есть DR версия 5.5 от Digital Research (она отличается наличием SPP, пакета для оптимизации по скорости и анализатора) и есть DR версия 5.6. Компилятор МТ+ отлично документирован и экспертами признавался намного более мощным и профессиональным инструментом, чем борландовский ТP 3.0, хотя TP благодаря IDE и позволяет значительно ускорить разработку и отладку программ. Но увы, TP не генерит код для КР580, только для Z80. Пока для освоения Паскаля использую самую древнюю версию MT+ от СМ-1800, т.к она русифицирована, а ускоритель SPP пока не нужен.

Для получения кода пригодного для РК86, несложно переписать в RUN-тайм библиотеке процедуру @BDOS так, чтобы в соответствии с передаваемым номером функции происходил вызов ПЗУ F800 по адресу высчитанному по формуле (F800 + func*3). Но это мне пока не надо, т.к отлаживать удобнее на CP/M-машине (точнее в эмуляторе ОРИОНА с CP/M). Малый объём ОЗУ РК не проблема (пока сама странслированная программа умещается в ОЗУ), т.к ключ $Z позволяет задать RAMTOP. Ограничения Паскаля по скорости можно устранить вкраплениями ассемблера (это также немного сокращает объём кода).

Чтобы получить программу в кодах КР580 работающую на РК86 без наличия на ней CP/M, надо решить проблему ввода/вывод, т.к ввод/вывод самого компилятора рассчитан на CP/M, т.е наличие в ОЗУ входа в CP/M BDOS и входов в CP/M-BIOS. Проще всего встроить вызовы ПЗУ F800 в виде INLINE-процедур написанных на ассемблере. Встроенный в MT+ ассемблер позволяет прямо в Паскаль программу встраивать куски на ассемблере (и даже двумя способами - в виде HEX-дампов и в виде мнемоник ассемблера).

Нужные для программирования РК простейшие процедуры COUT, MSSG, GOTOXY, XF81B, CONIN, RD_SCR... я написал в INLINE ассемблере в мнемониках КР580 быстро. К сожалению, INLINE ассемблер использует маловразумительные мнемоники КР580, а не всем понятные мнемоники Z80. Потому большие вкрапления ассемблера удобнее делать в виде прилинковываемого внешнего ассемблерного модуля, который можно писать в мнемониках Z80 (естественно избегая команд, которых в КР580 нет).

Не освоив полностью сам Паскаль, нет смысла сразу начинать писать игру для РК86. Сначала разумнее пописать простенькие программки и полностью разобраться в работе всех операторов, стандартных процедур и функций. Затем надо разработать "движок", т.е набор подпрограмм позволяющий выводить движущиеся динамически меняющиеся спрайты (спрайты состоящие из тайлов-символов). Но предварительно надо написать редактор спрайтов, позволяющий нарисовать 8 фаз спрайта и посмотреть как они выводятся на экран в динамике.

Конечно редактор спрайтов удобнее сделать программой для PC, т.к сам РК86 не позволяет загружать тайлы спрайтов в фонт. Но я (для тренировки) собираюсь написать на Паскале редактор спрайтов именно для РК86 в графическом режиме 128*129 (который требует альтернативный фонт, который как раз есть у меня на реале и поддержан в моём эмуляторе РК86 на ОРИОНЕ).

Ближайшее время (несколько недель) для освоения Паскаля буду писать простенькие программки. Пока на второй день изучения странслировал несколько программок уровня Hello World (чтобы освоить интерефейс с подпрограммами ПЗУ РК) и начал писать нечто вроде монитора РК86 на Паскале (не трудно сделать и с записью на МГ). Пока написал просмотр дампа. Это пригодится для отладки Паскаль программ. Добавлю к этому еще мини дизассемблер, это позволит удобно отлаживать. Для начала хочу понять насколько быстро разбухает код Паскаля.

Затем собираюсь написать текстов редактор, а потом, возможно, и ассемблер в мнемониках Z80. Может быть ещё что-нибудь простенькое, типа микро-ОС для ROM-диска или прошивателя ПЗУ 573 РФ2 или 556 РТ4. И только затем, набравшись немного опыта в Паскале, возьмусь за разработку редактора спрайтов и графических процедур для их динамического вывода.

И только потом можно будет начать делать игры для РК86 с тайловой графикой. Надеюсь к тому времени появится эмулятор РК86 с коммутируемыми фонтами. Без коммутации фонтов, т.е без минимальной графики, вообще нет смысла писать игры для РК86, т.к игры с бегающими по экрану ASCII-символами это просто уродство, которого достаточно написано ещё в 80-тые.
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Ср Май 02 2018, 19:16

3
Недавно разбирался с основами программирования на МТ-Паскале. Сам Паскаль работает великолепно, всё как в учебнике, да и находить и устранять ошибки удобно, диагностика достаточная. Но вот с ассемблером не всё оказалось так радужно, как казалось по документации.

С ассемблером при программировании для РК обязательно приходится разбираться, т.к стандартные процедуры Паскаля для ввода/вывода недоступны (т.к они работают через CP/M, которая в ОЗУ РК отсутствует). Таким образом программа для РК86, написанная на Паскале, без вкраплений ассемблера вообще ничего не может.

Например, если хочется напечатать на экране значение переменной в десятичном виде, то облом. Без собственных процедур ввода/вывода это невозможно - попытка использовать процедуры WRITE или WRITELN приводит к кошмарному улету. Потому всё, что программа может делать, это то, что могут делать подпрограммы ПЗУ РК86, причём их ещё надо как-то вызвать из программы на Паскале.

Потому для начала, используя INLINE вставки на ассемблере написал несколько простейших процедур для интерфейса с подпрограммами ПЗУ РК86. Например, вот самые простейшие:


{------------------------------------------------}

procedure cout(SYM: char);
begin
  INLINE( "LDA/SYM /
          "MOV C,A/
          "CALL/$F809 );
end;

function conin: char;
var RESULT:     char;
begin
  INLINE( "CALL/$F803/
          "STA/RESULT );
  conin := RESULT;
end;

procedure mssg(stradr: ukchar);
begin
  INLINE( "LHLD/STRADR/
          "CALL/$F818 );
end;

procedure hex(byt: byte);
begin
  INLINE( "LDA/byt /
          "CALL/$F815 );
end;

{------------------------------------------------}

procedure print(str: string);
label 10;
var     adr: integer;
       len: byte;
begin
   adr:=addr(str)+1; len:=sizeof(str);
10: inline( "LHLD/adr/
           "MOV C,M/
           "CALL/mcout/
           "INX H/
           "SHLD/adr/
           "LXI H/len/
           "DCR M );
  if len<>0 then goto 10;
end;

{------------------------------------------------}


Уже эти простейшие процедуры позволяют тот же минимальный ввод/вывод, что есть в ПЗУ РК86. Например, можно выводить строки текста задав их такой же INLINE-вставкой с завершающим нулём. Вот программа Hello World для РК86.

{------------------------------------------------}

prog HELLO_WORLD;
type    ukchar = ^char;
var     ukch: ukchar;

procedure mssg(text: ukchar);
begin
  INLINE( "LHLD/text/
          "CALL/$F818 );
end;

procedure thello;
begin
 INLINE ( $1F/10/'HELLO WORLD !'/0 );
end;

begin   (*  main  *)
       mssg(addr(thello));
 INLINE( "JMP/$F86C );
end.


А для вывода строк самого Паскаля процедура MSSG не годится, т.к в Паскале строки представлены иначе (для этого смотри процедуру print). Кстати, и вывести число в десятичном виде эти п/п-ммы всё-равно не позволяют (надо писать свою процедуру PR_DIG), т.к в ПЗУ РК не оказалось подпрограммы для вывода десятичных чисел. Но, если каким-либо образом "починить" работу оператора WRITE, то вывод десятичных чисел и строк станет возможным средствами самого Паскаля.

Как видите простейшие процедуры встроенный ассемблер позволяет написать. Но если попытаться написать чуть более сложную инлайн-процедуру на ассемблере, то выясняется, что никак не задать адрес переходов.

В документации указано, что тогда можно использовать идентификатор звёздочка (*), что заменяет текущий адрес трансляции (аналог $ в обычном ассемблере). Т.е можно писать "JMP/*+25/. Но увы, компилятор не воспринимает звездочку, даёт на неё ошибку. А с префиксом $ (что вообще-то HEX-префикс), т.е JMP/$*+25 транслируется, но если посмотреть полученный код отладчиком, то адрес перехода подставляется неверный.

Таким образом, я остался практически без INLINE-ассемблера. Без переходов можно написать только простейшие линейные процедуры. Выходом остаётся вставлять в процедуру INLINE-вставку в кодах, предварительно странслировав её обычным ассемблером прямо на рабочий адрес. Адрес размещения процедуры можно узнать из PRN-файла (используя прилагаемый дизассемблер Паскаля) или проще контроллируя код отладчиком. При этом эта INLINE-процедура должна стоять в начале исходника, чтобы при дальнейшем написании программы адрес процедуры уже не сдвигался. Тогда с помощью INLINE вставляется готовый дамп странслированной программы.

Но, т.к процедуру всё-равно надо транслировать обычным макроассемблером, то проще не вставлять её дампом (что вызывает необходимость контроллировать, чтобы адрес размещения совпал), а просто прилинковывать её при линковке, странслировав в виде внешнего модуля.

Да и вообще нашлось много нюансов, на которые пришлось потратить время. Например, надо писать не 'PUSH PSW', а 'PUSH P' , и не 'POP PSW', а 'POP PS', иначе возникает ошибка. Долго трахался с этим, а узнать это удалось только изучив дамп компилятора.

Но всё же надеюсь, что INLINE-ассемблер каким-то образом позволяет переходы. В документации на русском написано про звёздочку. Возможно переводная документация не соответствует, - от более раннней или более поздней версии. Видимо, надо читать читать документацию на английском, может быть там что-то найду.


Последний раз редактировалось: barsik (Вс Дек 23 2018, 11:13), всего редактировалось 2 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Сб Май 12 2018, 23:49

4
Нашёл ещё один пригодный для программирования для РК86 компилятор Паскаля. Скачать можно здесь. Пока только бегло пролистав документацию, выяснил что этот компилятор тоже пригоден для РК86, т.к даёт код КР580 и может выдавать COM-файл (а не INT запускаемый отдельным стартёром). На практике не проверял.  Так как пока меня вполне устраивает Паскаль МТ+, хотя документация (видимо, от другой версии и) местами не совпадает. Чуть позднее, изучив документацию к этому Паскалю, попробую написать Hello World на этом Паскале.

Также недавно нашёл примеры программ на Паскале. Есть несколько десятков исходников инструментальных программ для разных Паскалей, а также есть ещё ~300 исходников программ написанных именно для Паскаля МТ+. Это важно, т.к все Паскали для CP/M имеют различия и несовместимы по мелочам. Речь о исходниках от существовавшей в 80-тые годы BBS MT+ Users Group, от которой сохранился архив содержащий ~300 исходников программ написанных любителями на Паскале МТ+. По исходникам видно, что именно на Паскале было написано несколько десятков полезных инструментальных программ CP/M. Таким образом в качестве примера для целей изучения имеются сотни исходников Паскаль-программ (столько нет даже для CP/M Си, для них есть всего несколько десятков примеров).

А если Вы предпочитаете программировать для РК86 на Си, Коболе, Комале или других, то нет проблем, скачивайте здесь и начинайте писать.

Рассматривая в предыдущих постах CP/M-компиляторы, что пригоды для генерации кода КР580, я не упомянул один ЯВУ, который имеет шанс оказаться лучшим, чем Паскаль, а именно Ада, разработанный в начале 80-тых на базе Паскаля (в этом участвовал тот же автор Н.Вирт). Ясно что переход от Паскаля к Аде несложен, языки лексически похожи. Для нас удачно, что, например, в CP/M Суперсофт-Аду встроен ассемблер и код она генерит для КР580. Я уже подумывал ей заняться. Но теперь, когда нет препятствий к использованию ассемблера с Паскалем, в Аде пока нет нужды (глупо метаться между ЯВУ). Позже будет интересно сравнить качество компиляторов Ады и Паскаля, т.к компилятор Ады написан на 3-5 лет позже, возможно он эффективнее.

Кстати, в CP/M кроме бейсика, Си и Паскаля есть ещё несколько компиляторов старых и даже более новых ЯВУ, являющихся производными от Паскаля. А вот от Си ничего производного нет, т.к С++ возник позже, да и похоже объёма ОЗУ 8-ми разрядки для ООП просто не хватило.

В качестве старых ЯВУ для которых есть CP/M-компиляторы можно упомянуть PL/M, PL/1, Алгол и Фортран (не считая много других экзотических ЯВУ). Два последних, это математические языки, они не годятся для работы по железу. PL/M очень близок к ассемблеру и потому как ЯВУ он не очень мощный (хотя до появления КР580-компиляторов Паскаля в 1978, был популярен). Увы, для PL/M есть единственная книга на русском и её не скачать, можно только купить. Совсем древний PL/1 из 1964 немного похож и на PL/M и на Паскаль и скорее всего вполне подойдёт для разработки ПО для РК86. Важно, что литературы по PL/1 больше, чем для PL/M и его компилятор для КР580 кажется лучше, т.к более свежий, чем компилятор PL/M. Как упомянуто ранее, есть несколько CP/M-компиляторов Ада для КР580. Есть и современные кросс-компиляторы языков Ада, Модула-2 и Оберон (которые Паскаль-производные), но для РК они, увы, не годятся, т.к выдают код для Z80.

И всё же из этих ЯВУ для 8-ми разрядок наиболее удобным для программирования для ретро-ЭВМ любителем ПОКА следует считать Паскаль МТ+ и два Си, BDS и Aztec. Может они и не самые эффективные, но по ним достаточно литературы и документации и большое число примеров, конкретно для данных компиляторов.


Последний раз редактировалось: barsik (Чт Ноя 08 2018, 06:20), всего редактировалось 1 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Re: Использование ЯВУ для разработки программ для РК86

Сообщение  barsik Сб Июн 23 2018, 21:44

5
QUATTRO пишет:Если эта тема для "бородатых" программистов, и таким как я тут места нет, то извините
Нет тут бородатых программистов. Бородатые профессиональные программисты с окладом в $6000 в месяц сюда не ходят, у них на это нет времени (они и бородатые потому, что не хотят тратить время на бритьё).

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

Компиляция рэтро компилятором делается точно по инструкции пользователя, но не прямо в среде Windows или MSDOS, нужна среда CP/M. Это можно делать в любом эмуляторе, где есть CP/M. Причём желательно таком, где проще переносить файлы из Windows в CP/M. А если компилятор корректный, то можно запускать соответствующий CP/M компилятор и линковщик прямо в MSDOS, для чего нужно конвертировать эти CP/M программы в формат запускаемый в MSDOS c помощью GENCOM пакета 22NICE или подобных. Не все CP/M-программы работают под TSR-эмулятором, но компиляторы обычно MSDOS-корректные и запускаются в MSDOS.

Но я, оттого, что мне так удобнее сразу тестировать скомпилированную программу, использую свой эмулятор ОРИОНА. Для разработки простых программ для РК86 годится любой эмулятор любой 8-ми разрядки у которой есть входы F800 (т.е эмулятор РК, ОРИОНА или Специалиста с доработкой 2-мя диодами, чтоб возникли входы F800). Нужно, чтобы в таком эмуляторе была CP/M с высоким TPA (не менее 48 кб), иначе CP/M компиляторы ЯВУ не работают. А этим двум требованиям, увы, отвечает только эмулятор ОРИОНА. Т.к из-за мизерности объёма ОЗУ, CP/M для РК и Специалиста имеют очень низкий TPA, отчего в них можно использовать только компилятор ассемблера, а компиляторы ЯВУ и вообще все фирменные CP/M пакеты не идут.

Отредактировав текст программы на Паскале, запускаю BAT-файл. Он копирует все файлы с текстом Паскаль программы в каталог FILES.CPM и стартует эмулятор ОРИОНА. В каталог FILES.CPM ещё раньше скопированы все файлы MT+ нужные для компиляции и отладки. При старте эмулятор вылетает в CCP ORDOS. Там в квазидиске B (загруженный из подкаталога ORDOS.B), есть файл с именем EXT$.

Этот файл EXT$ автостартует при входе в ORDOS, что в некотором роде заменяет AUTOEXEC. В файл EXT$ переименован код CP/M оформленный как запускаемый ORDOS-файл (у меня все версии DOS в виде ORDOS-файлов, т.к это на порядок удобнее, чем старт DOS с системных треков дискеты, т.к позволяет выбирать  версию, а не иметь только одну и избавляет от подкачки). Можно и не использовать автостартовость ORDOS, а вручную вводить в CCP ORDOS командную строку с именем запускаемого файла DOS. Обычно это D1<ВК> (ORDOS файлы D0$ и D1$ это соответственно CP/M ОРИОНА для банок 0 и 1).

В моём эмуляторе после старта CP/M все файлы из подкаталога FILES.CPM перегружаются в эл.диск из ОЗУ ОРИОНА. Физически эл.диск это ОЗУ PC, потому размер эл.диска в моём эмуляторе невелик, ~280 кб (эмулятор использует только ~600 кб конвенционального ОЗУ MSDOS), но этого хватает (например, объём компилятора MT+ лишь ~150 кб). Т.е в папку FILES.CPM помещаю файл с именем AUTOEXEC.SUB следующего содержания.

Код:
D7
MTPLUS P $PAX
MTPLUS MOD1 $PAX

Первая строка это запуск консольного драйвера CP/M, т.к без него в CP/M ОРИОНА только КОИ-7, а все фирменные программы используют ASCII. Вторая строка компилирует основную программу с именем P.PAS (которуя пишу и отлаживаю в данный момент). А третья строка компилирует модуль связи MOD1.PAS тоже на Паскале, обеспечивающий интерфейс с подпрограммами ПЗУ РК86, который общий для всех программ, потому и вынесен в отдельный модуль.

Этот модуль связи написанный на Паскале может заменяться эквивалентным модулем написанным на ассемблере, который содержит процедуры для интерфейса между Паскалем и п/п-ми ПЗУ РК86, а также процедуры работающие прямо по железу РК, что Паскаль, естественно, не умеет. Это приходится применять для сложных процедур и функций. Этого можно было бы избежать, ограничившись INLINE ассемблерными вставками, если бы встроенный INLINE ассемблер позволял переходы. Но увы, несмотря на то, что в документации написано, что символ '*' адресует текущий адрес трансляции, это не работает. Без переходов оператор INLINE позволяет встроить в программу только линейный фрагмент на ассемблере. Для простого вызова п/п-мм ПЗУ этого достаточно. Хотя выгоднее написать на ассемблере и включить в программу свои аналоги п/п-мм ПЗУ, что сделает программу более мобильной. В случае внешнего модуля на ассемблере вместо 3-й строки ставится строка: M80 =MOD1.ASM, которая компилирует с ассемблера.

Обычно при трансляции возникает куча ошибок трансляции и приходится их исправлять. Тогда нажимаю F9 и вылетаю в монитор-отладчик эмулятора. Здесь набираю Q<Enter> и вываливаюсь из эмулятора назад в Windows. Где в окне редактора исправляю текст и повторяю компиляцию снова запустив эмулятор.

Если всё странслировалось без ошибок, то в ком.строке CP/M пишу S L<ВК>, отчего SUBMIT запускает пакетный SUB-файл L.SUB (SUB-файлы это CP/M аналоги BAT-файлов MSDOS). Это просто, чтобы меньше набирать текста. Можно просто ввести командную строку для запуска линковщика:

LINKMT P, MOD1, PASLIB /S

Иногда, например, чтобы получить и посмотреть ассемблерный текст в который компилируются операторы Паскаля или, чтобы подключить отладчик, добавляются другие ключи. При компоновке тоже постоянно возникают ошибки линковки, приходится их устранять и всё повторять. Когда программа наконец скомпилирована и слинкована, то на эл.диске возникает файл P.COM. Я загружаю его в ОЗУ на адрес 100 командой ZS3 P.COM<ВК> и делаю сброс ОРИОНА нажав на F8.

Снова оказываюсь в ORDOS. Только теперь автостарта EXT$ не происходит, т.к квазидиск B затёрт при старте CP/M в банке 1 (а сама копия CP/M для её рестарта сохраняется в банке 6 ORDOS файлом с именем CPM$). Теперь мне надо перенести мою программу, что осталась в банке 1 (где работает CP/M)  в банку 0, где программе надо работать (т.к в банке 1 она работать не может потому что ПЗУ F800 можно вызывать только из банки 0, т.к экран в банке 0). Копировать из банки в банку на ОРИОНЕ умеет только монитор M3-EXT.

Для этого ввожу команду MON<ВК>, отчего из ROM-диска стартует M3-EXT. С его помощью командой P0,C3FF,1,0 копирую память банки 1 в банку 0. При этом и программа, что была загружена на B1:0100 отладчиком ZSID3, переносится в банку 0 на адрес 100. Остаётся для её запуска ввести команду G100<ВК> и можно смотреть как работает программа написанная на Паскале.

Так можно проверить на ОРИОНЕ только корректные программы РК86, что делают ввод/вывод только подпрограмами ПЗУ. Если же я делаю программу, что напрямую лезет в экранный буфер РК86, сама напрямую опрашивает матрицу клавиш или использует альтернативный фонт, то проверить такую программу на ОРИОНЕ нельзя.

Но по счастью у меня как раз есть эмулятор РК86 на ОРИОНЕ. Чтобы проверить такую программу, я записываю проверяемый файл в квазидиск ORDOS командой SP@,100,endaddr<ВК> и запускаю эмулятор РК на ОРИОНЕ командой EM<ВК>.

Быстрее будет компиляция файлами MSDOS прямо в Windows. Это точно будет быстрее, т.к при компиляции в эмуляторе ОРИОНА у меня каждый раз теряется куча времени на запуск самого эмулятора.

Для этого с помощью GENCOM из пакета 22NICE делаем MSDOS стартовые файлы из файла компилятора и линковщика MTPLUS.COM и LINKMT.COM (для чего сначала переименовываем их в *.CPM и запуская GENCOM получаем их MSDOS стартёры). Что позволяет их стартовать BAT-файлом прямо в Windows. Но получив готовую скомпилированную программу, её придётся вручную сконвертировать в GAM или RKR файл и запустив какой-либо эмулятор РК86 считать в эмулятор этот Tape-файл. После чего для проверки можно программу запустить командой G100<ВК>.


Последний раз редактировалось: barsik (Чт Ноя 01 2018, 01:24), всего редактировалось 1 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Пн Июл 09 2018, 14:17

6
Пока искал информацию про Паскаль МТ+ вот здесь мне попалась интересная статья kakos_nonos-а про компиляторы ЯВУ. Автор озадачился той же проблемой (поиском компиляторов для программирования РК86), хотя его выводы немного отличаются. Автор также пришёл к выводу, что наиболее победительный язык высокого уровня для программирования РК86 это PL/M (точнее не оригинал PL/M из 1973, а его более продвинутый вариант PLMX из 1979).

Однако выводы автора относительно неактуальности Паскаля МТ+ в корне ошибочны. Автор не разобрался в ключах трансляции и подключал ненужные в конкретной программе библиотеки (например, зачем подключать библиотеку с плавающей точкой, если все расчёты идут над целыми числами). Считать с точностью 38 цифр после запятой в программах для РК не требуется, а банковских программ для РК никто писать не собирается. Потому автор получал для простейшей программы объём кода в 26 кб из чего и сделал вывод о непригодности Паскаля МТ+. Я странслировал ту же программу и получил объём кода менее 4 кб (причем объём собственно программы едва 300 байтов, остальные 3.5 кб это RUN-тайм библиотека, которую не проблема сократить в объёме в разы). Я получал объём минимальной программы на МТ+ менее килобайта, кстати, на Си размер минимальной программы в разы выше.

Нашёл ещё один Паскаль, который возможно может быть использован для КР580. Это Hisoft Pascal80. Вообще-то он для Z80. Он нормально компилирует в CP/M ОРИОНА на Z80, но выходной код компилятора в моих пробных экспериментах почему-то работал и на КР580.

Этот Паскаль был написан для ZX-Spectrum в 1983. В 1984 вышла версия для Amstrad CPC и версии для CP/M 2.2 и 3.0 (версии для CPC поддерживают железо CPC, графику и т.п). В 1985 вышла версия для MSX, а позднее и для других машин с Z80. Интерес представляет версия для CP/M 2.2.

Читал, что по эффективности этот Паскаль считается более эффективным (код короче и быстрее), даже чем Турбо-Паскаль. Простые опытные программы, что я компилировал давали вполне компактный код (менее 4 кб). Удачно, что, т.к этот компилятор широко использовался, документации вполне хватает. Кстати, в именах в программах для HP80 не используйте символ "подчёркивание" (код $5F) и у меня почему-то транслировалось только, если все операторы были в верхнем регистре (возможно нужно задать какой-то упр.ключ).

Сам компилятор работает только на Z80 (в эмуляторах CP/M для КР580 не работает). Пока не могу точно проверить работает ли весь генерируемый код в системе с КР580, т.к, хотя у меня есть эмулятор ОРИОНА на КР580, но нет CP/M для ОРИОНА, что работает на КР580. Это проверить можно в эмуляторе EMU от b2m, но там неудобно переносить файлы в образы диска, потому для прогона CP/M-программ я им не пользуюсь.

Потому тестирование кода из под компилятора проводил на IBM PC под MSDOS TSR-эмулятором 22NICE. Этот эмулятор автоматически переключается на Z80, если в программе встречается хоть одна команда Z80 (если же Z80-команд нет, то флаги ставятся точно, как у КР580). Если сгенерировать COM-файл с ключом "PROCESSOR=TEST", то выдаётся сообщение использовала программа команды Z80 или нет. Так вот, несколько простых Паскаль программ я странслировал с помощью компилятора HP80 и прогнав их под 22NICE, выяснил, что команд Z80 в их коде нет.

Естественно, по простейшим программам ещё нельзя судить. Нужно испытать на больших программах в которых задействованы все операторы этого Паскаля. К сожалению, это специфичный Паскаль (например, в нём нет оператора STRING) и проверить его на программах написанных для TP или MT+ не получается. Нужно изучать документацию, чтобы понять как писать программы для такого компилятора. Но пока меня устаивает и Паскаль МТ+.

Hisoft Pascal80 можно скачать здесь. Сам компилятор (не дистрибутив, лишь сам компилятор), который я проверял - это файл HP80.COM  в подкаталоге HP80. Полный дистрибутив в файлах образов дисков CPM Sam Coupe и DSK-образах для CPC (для считывания файлов из образов дискет CPC используйте там же приложенную утилиту чтения образов дискет CPC).

Наконец также удалось найти компиляторы ЯВУ для процессора 6800. Если для процессора 6502 можно скачать множество кросс-компиляторов ассеблера и ЯВУ (есть даже кросс-IDE), то для процессора 6800 с этим намного сложнее. Если кое-какие ассемблеры для 6800 имеются (есть даже кросс-ассемблер для CP/M, хотя и не макро), т.к ассемблер был необходим при разработке программ контроллеров на 68xx, то компиляторы ЯВУ (из-за того, что бытовых ЭВМ на 6800 практически не было), - распространены намного меньше.

Но всё-же и эта проблема в итоге решилась. В качестве компилятора Си нашёлся многоплатформенный кросс-компилятор Си от Hi-Tech. А в качестве  компилятора Паскаля удалось найти компилятор Паскаля для болгарского компьютера "Пылдин-601". Есть версия Паскаля и для оригинальной DOS этой машины и, главное, есть кросс-компилятор для PC. Кстати и компилятор ассемблера для Пылдина, это, похоже, лучший компилятор ассемблера для 6800 (и он также есть в кросс-версии для PC). Нашёл также компилятор Паскаля для процессора 6502.


Последний раз редактировалось: barsik (Пн Ноя 12 2018, 15:03), всего редактировалось 1 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Ср Окт 31 2018, 23:10

7
Не писал на РУ-ЭВМ последнее время по несколькимм причинам. Во-первых, особых успехов по программированию на Паскале нет, за это время не занимался этим. Во-вторых, некоторое время и не мог писать в форум по техническим причинам.

Должен пояснить, что в программировании я сейчас вообще почти полный чайник, хотя в 90-тые и пытался освоить программирование, в том числе для PC. Немного программировал в MSDOS на ассемблере, Турбо-бейсике, Турбо-Паскале и Турбо Си для MSDOS. А когда в начале 21-века до меня наконец дошло, что угнаться за прогрессом невозможно (пока без всякой помощи или хотя-бы консультаций самостоятельно несколько лет осваиваешь новый инструментарий, он успевает уже устареть и надо начинать всё сначала), то понял, что просто впустую трачу время пытаясь освоить Visual Basic, Visual Си и Delphi. А сейчас почти 20 лет спустя и те знания по программированию на ЯВУ, что поимел, полностью забылись. А вот, кстати, ассемблер, слишком прост и нагляден (особенно ассемблер Z80), его не забудешь, даже при желании.

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

Отладчик при этом не нужен, - когда возникает неясность, в программу вставляются отладочные фрагменты, т.е останов в контрольных точках с печатью содержимого регистров и ячеек, имитируется как бы прогон под отладчиком. Метод частых перетрансляций намного эффективнее, чем древний (вынужденный из-за медленности техники) метод, когда программист несколько часов набирает исходник программы, а затем начинает долгими часами прогонять её под отладчиком, пытаясь обнаружить ошибки. Это делалось потому, что каждая перетрансляция длится очень долго и сильно изнашивает дисковод.

Сначала я пытался использовать компилятор Паскаля МТ+ в эмуляторе 8-ми разрядки, в котором эмулируется дисковод с CP/M. Но оказалось, что исходники реального размера (тысяча и более строк) на скорости 8-ми разрядки транслируются слишком долго, - до 10 минут. Удаётся ускорить потери времени на трансляцию до одной-двух минут, если не перетранслировать всякий раз всю программу, а лишь те небольшие модули в которых последний раз делались изменения. Но всё-равно, вместо 20 перетрансляций в час кросс-средствами, в эмуляторе за то же время удаётся успеть сделать всего 3-5 перетрансляций.

Чувствительным неудобством компилятора Паскаля оказалось то, что он останавливает трансляцию по первой же ошибке. Ассемблер транслирует всю программу и выдаёт сразу все ошибки. Тогда видя их в листинге трансляции, их все сразу можно исправить за одну итерацию. А на Паскале, если в исходнике есть 50 ошибок, то для каждой ошибки надо выполнять трансляцию, чтобы компилятор указал в какой строке и какой номер ошибки возник.

Всё это привело к тому, что эффективность Паскаля с использованием компилятора в эмуляторе или реале оказалась не лучшей, чем при программировании на ассемблере. Выигрыш за счёт использования ЯВУ обнулил медленный компилятор. Хотя, конечно, ЯВУ облегчает разработку программ со сложной логикой, многое, что крайне сложно сделать на ассемблере, без всякого напряжения делается на ЯВУ. Программы на ЯВУ намного понятнее и их на порядок легче сопровождать и модифицировать.

Т.о ясно, что трансляция в эмуляторе 8-ми разрядки это плохой вариант. Чтобы повысить эффективность требуется до нуля сократить потери времени на саму трансляцию. Это достигается при использовании кросс-компилятора Паскаля. Но не смог найти кросс-компилятор Паскаля в коды КР580/Z80. А вот кросс-компиляторов Си нашёл с десяток. Можно использовать конвертор исходников на Паскале в исходник на Си. Тогда текст из под конвертора можно транслировать кросс-компилятором Си. Но увы, пока не нашёл кросс-компиляторов Си под КР580, все под Z80. Похоже, что вне бывшей СССР КР580 малопопулярен. Использование Паскаль+Си невыгодно тем что лишний этап на конверсию чреват дополнительными ошибками.

Для ускорения трансляции, если используется Win XP, кроме кросс-компиляторов, можно прогонять CP/M-компилятор Паскаля под CP/M TSR-эмулятором для MSDOS. Для этого следует использовать версию МТ+ от Digital Research, а не раннюю русифицированную версию от СМ-1800. Грамотно составив BAT-файл и используя вспомогательную конвертирующую программу, сейчас мне удаётся транслировать Паскаль исходник в ORD-файл всего за несколько секунд. Но такой ORD-формат файлов использует только мой эмулятор. Если используются эмуляторы EMU или EMU80, то для них нужно писать специальный конвертор, который конвертирует блок кодов в TAPE-формат принятый для этих эмуляторов или же вручную как-то переносить тестируемую программу в образ дискеты.
QUATTRO пишет:Я так и не понял, как привязывать программу к стандартным подпрограммам РК86. Ведь действительно, как barsik уже писал, ничего не получится без привязки к стандартным подпрограммам Монитора.
Проблема в том, что в Паскале нет оператора CALL/USR как в бейсике. Зато есть способ это сделать за счёт встроенного инлайн-ассемблера. Потому и приходится написать процедуры или функции, которые не делают ничего кроме вызова п/п-рамм ПЗУ.

Насчёт того, что я "писал, что ничего не получится без привязки к стандартным подпрограммам ПЗУ". Вряд ли я писал именно так. Скорее всего имелось ввиду, что использовать имеющиеся готовые подпрограммы проще всего. Если при программировании на ассемблере стандартные п/п-ммы ПЗУ существенно упрощают программирование, то и из ЯВУ это тем более имеет смысл делать.

Фраза, что на ЯВУ без использования подпрограм ПЗУ совсем ничего не получится, - неверна. Ведь полно РК-игр, что не лезут в ПЗУ, напрямую считывая матрицу клавиш через ППА и записывая байты напрямую в экранный буфер. Для машины с текстовым экраном программирование на ЯВУ без использования подпрограмм ПЗУ конечно получается в разы тормознее, хотя, благодаря мощности ЯВУ, совсем не сложно. А вот для графических ЭВМ это сделать сложнее, и к тому же в результате получится совсем тормоз.

Чтобы не вызывать ПЗУ, можно написать на самом Паскале аналоги ПЗУ-шных подпрограмм вывода на экран и опроса клавиатуры. Ясно, что это тормознее, но не сложно. На Паскале написание подобных процедур проще, чем на ассемблере. Например, вывод символа, это просто по текущим координатам POSX и POSY вычисление экранного адреса по формуле и занесение туда байта. На Паскале это десяток строчек (и даже меньше, если ролик сделать ассемблером), тогда как на ассемблере это 300 строк. Так же и опрос клавиатуры - делаем на Паскале то же, что делает подпрограмма F81B, - выкидываем в порт А "бегущий ноль", считывая с порта B, до тех пор пока не будет нуля в одном из разрядов. А опрос клавиш не входящих в матрицу - УС, СС, РУСЛАТ это вообще один хитрый оператор Паскаля (считать ячейку с маской). То, что на ассемблере пишется за многие часы или дни, на ЯВУ пишется за единицы минут.

Если скоростей Паскаля не хватает, можно сделать то же самое на ассемблере, т.е взять из исходника ПЗУ РК86 несколько основных подпрограмм, странслировать каждую отдельную подпрограмму как процедуру и в виде инлайн-дампа встроить в Паскаль программу. Тогда будут быстрые Паскаль-процедуры выполняющие ввод/вывод на РК86 без доступа к его ПЗУ.

Но всё-же проще использовать Паскаль-процедуры, реализованные с использованием инлайн-ассемблера, которые ничего не делают кроме переадресации на подпрограммы ПЗУ. Вызовы ПЗУ заменяются инлайн-вставкой, например, INLINE ( "CALL/$F803" ); что мало отличается от CALL 0F803H в ассемблерной программе. Оформление этого как отдельные процедуры и функции нужно лишь, чтобы не повторять всякий раз один и тот же код.

Как писал выше, в бездисководной и без-CP/M-ной системе стандартные паскалевские операторы ввода/вывода (READ, WRITE) не работают. Использование собственных процедур ввода/вывода быстрее и удобнее, но начинающему изучение Паскаля всё-же желательно, чтобы все операторы работали как в учебнике, чтобы ввод/вывод, по крайней мере на консоль, делался стандартными операторами READ и WRITE.

Паскаль программа это делает вызывая функцию @BDOS библиотеки времени исполнения, которая, естественно, просто загружает параметры в регистры BC,DE и делает CALL 5. Документация рекомендует для не-CP/M систем переписать функцию @BDOS. Но исходника RUN-тайм библиотеки нет и непонятно как это сделать. Переопределение функции @BDOS не помогает, выдаётся ошибка двойного определения идентификатора.

Но недавно я кое-как решил эту проблему. Проще всего результат достигается переопределением процедур @WNC и @RNC. При их переопределении ошибки не возникает. После вставки в текст программы нижеприведённого куска, оператор WRITE для консоли начинает работать, он работает используя не функцию CP/M, а подпрограмму РК86. Но работает только для консоли (не для DOS-файлов, только для стандартного устройства OUTPUT, который в Паскале тоже является файлом).

procedure @WNC(SYM: byte);
begin
  inline( "LDA/SYM /
          "MOV C,A/
          "CALL/$F809 );
end;

function @RNC: char;
var result: char;
begin
  inline( "CALL/$F803/
          "STA /result );
  @RNC := result;
end;


А вот для оператора READ всё сложнее, после вышеприведённого переопределения @RNC при READ программа всё-равно виснет в без-CP/M-ной системе. Потому что ввод/вывод в Паскале не прямой, а буферизованный (для консоли он происходит из стандартных файлов INPUT/OUTPUT). Потому, чтобы заработал READ надо переписать и функцию GET, что уже не так просто, т.к она работает с файлом. Оператор READ в Паскале, это не просто ввод строки, а ввод всего. Он позволяет ввод любых переменных, строк, символов, простых чисел (как десятичных, так и HEX), REAL-чисел (т.е дробных десятичных чисел) и даже любых данных любого размера (называемых записями) из открытых файлов.

Дробные десятичные числа с точностью в 38 цифр после запятой необходимы для расчёта полёта на Луну или банковских программ, но для написания РК-игр это не надо. Т.е полноценный READ не нужен, достаточно трёх подпрограмм: ввода строки (GETLIN) и ввода из полученной строки десятичного или HEX-числа. Тем не менее полезно переопределять $RNC на пустой оператор, т.к это существенно сокращается объём кода программы. Если же всё-же Вам надо вводить дробные десятичные числа, то чтобы заработал оператор READ, придётся эмулировать работу CP/M. Эта задача решается перехватом обращений к CP/M BDOS по CALL 5.

Для этого в начале программы выполняется вот такой фрагмент: poke(5,$C3); dpoke(6,addr(CPM)); В программе должна быть функция CPM, которая должна эмулировать все недисковые функции CP/M. Эта функция по сути является эмулятором BDOS CP/M. Я сделал её как на Паскале, так и на ассемблере (смотри спойлер ниже). Но это громоздко, использовать имеет смысл только, если в программе необходим ввод дробных чисел. А для вывода по WRITE вариант с @WNC намного проще и экономнее. К тому же своя процедура ввода REAL-числа может оказаться короче, чем объём кода эмулятора BDOS.

Впервые идею эмулятора BDOS CP/M придумал С.Н.Попов (он же разработчик РК86) опубликовав исходник в ж.МПСС (06.1987, стр.18), а коды такого эмулятора консольных функций CP/M уже специально для РК (на адрес 0...FF) он же опубликовал в 1988 в ж.Радио.

Этот эмулятор консольных функций предназначался как раз для использования на РК86 недисковых CP/M-программ и чтобы программы РК написанные с использованием CALL 5, в будущем, когда на РК появится CP/M (на базе RAM-диска или даже с настоящим дисководом) не пришлось бы адаптировать для неё.

Использование в инлайн-вставках меток для команд переходов также кое-как извращённо удалось решить. Для этого в исходнике на ассемблере полученном после отработки DIS8080 приходится смотреть и записывать на бумажку смещения меток от начала процедуры. А в начале прогона программы оператором ADDR получаем адрес конкретной ассемблерной инлайн-вставки и корректируем байты где нужны абсолютные адреса, добавляя к значению адрес начала процедуры.

Есть ещё один способ, когда инлайн-ассемблерная процедура копируется на другой заранее известный адрес, отчего адреса меток становятся известными и код не нуждается в коррекции, по сути это метод широко применяемый для вставки ассемблерного кода в бейсике.

Вообще, для экономии ОЗУ и удобства использования на РК программ созданных для CP/M, в том числе и написанных на Паскале, можно в свободный участок ПЗУ, например, в адреса F000...F7FF прошить эмулятор консольных функций CP/M (естественно перетранслировав на соответствующие адреса). Нижеприведённый простейший эмулятор консольных функций BDOS имеет размер всего в 256 байт и позволяет в оригинале использовать все недисковые (и нелезущие в CP/M-BIOS) программы CP/M. Перед стартом CP/M-программ, написанных самостоятельно на ЯВУ или взятых из архивных сайтов CP/M достаточно выполнить инициализацию (при которой формируются JMP-ы в адресах 0000, 0005 и JMP на вход в BDOS в вершине ОЗУ).

эмулятор консольных функций BDOS CP/M:

QUATTRO пишет:Как я понимаю, в конечном итоге я должен получить какой-то код по адресам, например 0000 - 00FF, потом это все как то перенести на тот же РК86 и уже по адресу G0000, запустить. В эмуляторе это все сделать проще, но и все же, надо сначала получить результат, тот же файл HEX-код или хотя бы файл с расширением GAM/RK и уже его запускать в эмуляторе.
Естественно, для прогона результирующий код из под ЯВУ надо перенести в эмулятор или реал и разместить по рабочим адресам, а затем командой G запустить с стартового адреса. Но вот насчёт адреса 0 не всё просто. Без всяких ухищрений все CP/M компиляторы на выходе выдают программы стартующие с адреса 100H. Тут уж ничего не поделать, это свойство CP/M. Но это даже имеет свои плюсы. Вы без хлопот получаете 256 байт под разные буфера или свой внешний программный код.

Например, во все DOS я всегда вставлял блок RST. Это блок входов заимствованный из одного заграничного компьютера. RST команды короткие и удобные. Например после загрузки RST-блока текст удобно выдаётся командой RST 18, разместив ASCIIZ-строку сразу же за кодом команды RST, это ускоряет и экономит 5 байтов при каждом выводе и текст располагается там же где его выводят, что облегчает изучение программы.

HEX-формат выдают нелинкующие ассемблеры первой волны из 1976-1978 годов. HEX-формат появился в 60-тые, рассчитан на перфоленту и сейчас является полнейшим анахронизмом. Он разработан для хранения на ненадёжном носителе, а также позволяет при вводе с перфоленты прямо в ходе процесса загрузки определить, что произошёл сбой. Нет никакого смысла использовать такие ассемблеры. Зачем транслировать в HEX, чтобы потом специально приходилось дополнительно отдельной программой конвертировать в код. Вам же не надо выводить файл на перфоленту. Хотя 40 лет спустя этот формат стали применять в прошивателях РПЗУ, т.к он позволяет хранить коды с адресами и фрагментами. HEX-формат для РК86 неприменим, для него нужен код программы.

Получить сразу файл в TAPE-формате эмуляторов (т.е *.GAM или *.RK) на Паскале не получится. А вот на ассемблере это делается без проблем, там просто в начале исходника операторами DB вставляется TAPE-хеадер, а в конце файла также вставляются требуемые байты синхронизации и контрольная сумма. Потому, если нужен TAPE-формат эмуляторов, то конвертировать код программы в такой формат придётся вручную. Но разумнее написать на Паскале простую программку, которая конвертирует в требуемый для конкретного эмулятора формат (это написать просто и будет дополнительная тренировка в Паскале). Можно такой конвертор написать в Паскале для PC или в Паскале для CP/M (тогда для запуска в MSDOS нужен резидентный CP/M-эмулятор типа 22NICE)

Спойлер:

Чтобы знать при программировании на ЯВУ что происходит, удобно вставлять в заданных стоп-точках вывод дампа (с ASCII). Это позволяет увидеть как представляются и передаются процедурам данные, увидеть переменные, т.е посмотреть как Паскаль работает изнутри. Хотя, в отличие от BDS и AZtec Си у Паскаля МТ+ есть отладчик, и для этих же целей можно использовать его, но на это теряется намного больше времени. Кстати, при программировании на ассемблере при нужде я также к программе прилинковывал модуль с аналогичной подпрограммой вывода дампа.

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

dump.pas:

А вот аналог этой процедуры на ассемблере:

dump.asm:

Вот функция GETLIN, ввод строки символов с клавиатуры. Она также полный аналог аналогичной программы на ассемблере. И также в отличие от аналогичных п/подпрограмм отечественных ЭВМ имеет почти полноценный редактор строки и тимплет символов. При вводе строки нажимая <забой> или <курсор влево> можно последовательно удаляя символы слева от курсора дойти до места опечатки и исправить, но в отличие от, например, подпрограммы ввода в бейсике РК, не требуется заново вводить удалённые символы, по нажатию <курсор вправо> удалённые справа символы восстанавливаются.

Тимплет символов это память на предыдущую команду, которую ввели этой же процедурой. Строка из тимплета вставляется по нажатию клавиши <курсор вверх> в нулевой позиции строки. Например, Вы вводите команду, запускаете, но она не срабатывает из-за опечатки. Можно не набирать всю строку заново, а вызвать строку из тимплета и отредактировать. Это экономит время, в DOS и нортонах я использовал только такую GETLIN. Кроме того, GETLIN позволяет определить, что была нажата клавиша искейп (в терминологии РК это АР2) или клавиша <F4> или Control-C, т.е был выполнен аварийный выход для прерывания ввода. Например, когда в нортоне пользователь вдруг передумал переименовывать файл. При нажатии АР2 возращается число 255, при Control-C - 254, а при нормальном завершении ввода нажатием <ВК> возвращается число введённых символов.

getlin.pas:

А вот то же самое на ассемблере (это для ОРИОНА с Z80, но годится и для других, если соответственно изменить служ.ячейки ПЗУ).

getlin.asm:


Последний раз редактировалось: barsik (Пт Мар 13 2020, 03:04), всего редактировалось 8 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Пригодная для использования версия Паскаля МТ+

Сообщение  barsik Ср Ноя 07 2018, 10:22

8
Хорошая новость для любителей 8-ми разрядного Паскаля и микро-ЭВМ с процессором КР580.

Наконец-то, решилась главная проблема современности для Паскаля-МТ+. А именно проблема меток в ассемблерных инлайн-вставках. Оказалось, что виновата фирма MicroSystems, оригинальный разработчик Паскаля МТ+. Которая разработала этот Паскаль в 1978-80 годах, а в 1981 продала его фирме Digital Research, которая сначала продавала его под своей маркой в неизменном виде с тем же номером версии 5.5. Но в 1983 году Digital Research переработала этот компилятор и выпустила конечную версию 5.61.

Хотя объём всех модулей последней версии 5.61 увеличились всего на 3%, но различие есть и список исправленных ошибок существенный. Также документация переработана и дополнена большим числом примеров. Увы, в СССР попала более ранняя версия от MicroSystems (1980) с соответствующей документацией. С Корвета она попала на самодельные 8-ми разрядки. В этой версии сообщения в коде компилятора были русифицированы. Возникает справедливая претензия к работе советских служб промышленного шпионажа, - почему в страну завезли раннюю версию, а не более качественную последнюю версию. Вот из-за таких глупых ошибок СССР и не смог догнать и перегнать Америку, как планировалось.

Большинство CP/M архивных сайтов содержат и распространяют версию 5.5, лишь на немногих из них есть версия DR 5.61. Так вот оказалось, что все предыдущие версии МТ+ до Digital Research версии 5.61, в том числе и те, что имели хождение в СССР имеют ущербный, а точнее просто дохлый, встроенный ассемблер. Как уже указывал выше, в этих версиях в инлайн ассемблере нет переходов на метки. Т.е символ * обозначающий текущий адрес трансляции, не работает. И от типа процессора КР580/Z80, как можно предположить, это не зависит.

Это явная дохлота. Вряд-ли в версии 5.5 это ещё не реализовано, а лишь описано в документации на будущее. Скорее всего, в более ранних версиях это работало, а в версии 5.5 сдохло. Иначе как объяснить, что это описано и в более ранней документации для версий 5.1 и 5.2. Увы, версий 5.1 и 5.2 не встречал, проверить нельзя. Как бы там ни было все версии 5.5 и от MicroSystems и от Digital Research имеют полудохлый инлайн-ассемблер, в нём не работают относительные метки.

Ранее я пользовался отечественной версией 5.5 с русифицированными сообщениями, т.к по русски мне читать удобнее. Но пытаясь понять в чём дело попробовал и кучу англоязычных версий 5.5, что брал из CP/M-архивных сайтов. Невозможно было предположить, что фирменный пакет продаваемый за 400 USD в 1981 году содержит ошибку. Но недавно скачал версию DR 5.61, чтобы проверить не даёт ли он более эффективный код, чем версия 5.5. И заодно проверил инлайн-ассемблер.

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

Таким образом, из-за чьей-то ошибки 40 летней давности я трахался несколько месяцев, изобретая хитроумные методы, чтобы обойти указанный дефект. А виновата именно фирма производитель. Т.к во всех копиях дистрибутива Pascal МТ+ 5.5, что были сохранены пользователями и впоследствии попали в CP/M-архивы, одна и та же дохлота. Это значит, что именно в таком дохлом виде это и продавалась. И только фирма Digital Research это исправила. Так, что советую всем удалить из всех архивов версию Паскаля МТ+ 5.5 - она просто дохлая, непригодная для использования встроенного ассемблера.

Ещё одной приятностью оказалось, заметное сокращение объёма кода при переопределении операторов посимвольного ввода/вывода - @RNC и @WNC. Оказалось, что компилятор очень грамотно использует свою библиотеку. Он добавляет из неё не все функции, а только те, что используются в программе. Потому переопределив операторы @RNC и @WNC, заменив тем самым каждую из них всего на пару команд ассемблера (как видно из нижеследующего спойлера), мы выигрываем в объёме кода ~800 байтов. В итоге минимальный размер программы может быть совсем маленьким, - менее килобайта (и даже всего полкилобайта, если операторов мало).

Сейчас я транслирую Паскаль программы под TSR эмулятором CP/M в MSDOS (т.к у меня Win XP, а она позволяет прогонять MSDOS программы) и потому трачу всего 3 секунды на трансляцию Паскаль-программы (собственно сама трансляция длится 0.1 секунды, 2 секунды тратится на то, чтобы увидев сообщение, что нет ошибок нажать пробел и ещё секунда уходит чтобы нажать на пробел второй раз после успешной линковки). Ещё секунда уходит на конверсию COM-файла в ORD и загрузку эмулятора ОРИОНА. Т.е собственно на компиляцию у меня теперь уходит так же мало времени как и при программировании на ассемблере - в час можно делать ~25 и более раз цикл модификации Паскаль-исходника, трансляции и проверки работы полученной программы.

Теперь после получения ассемблера я снова переписал подпрограммы нижнего уровня уже целиком на ассемблер. Для написания игр для РК можно немного выиграть в скорости, если делать вывод напрямую в экран, что собственно и делали программисты любители. Но они это делали потому что это проще, чем функциями. Особой необходимости в этом не было, скоростей в РК хватало и при работе через ROM-BIOS.

А вот при ЯВУ надо уже экономить ресурс, - программа на Паскале, как минимум, раз в 5-6 тормознее, чем аналог написанный на ассемблере. Если делать вывод прямой записью в экран и для расчётов экранных позиций использовать табличный метод, то достигается максимально возможная скорость вывода.

В Паскале с экраном работать намного проще, чем ассемблером. Это просто массив screen[X,Y], где X и Y это столбец и строка экранной позиции и вывод на экран это всего один оператор (все расчёты выполняются неявно и отпадает утомительное позиционирование курсора перед выводом и чтением байта с экрана). Также Паскаль резко упрощает разработку в псевдографике (в граф.режимах 128*60, 128*129 и даже 192*90), что на ассемблере сложно.

Можно сразу делать программы универсальными, т.е не только для РК, но и для ОРИОНА или ИРИШИ. Если грамотно выбрать алгоритм, то при этом требуется менять только несколько процедур нижнего уровня. Тогда достаточно включать в линковку модуль для конкретной машины и на выходе без лишних хлопот будут получаться программы для разных ЭВМ, без модификации кода самой программы.

В крошечных инлайн-вставках легко посчитать адреса вручную. Чтобы исключить ошибки при больших вставках удобно странслировать ассемблерный фрагмент вставив в исходник строки вычисляющие оффсеты (типа OFFS1 EQU METKA-$). А для экономии времени, чтобы не набирать строки ассемблера, можно вставлять ассемблерные процедуры готовым дампом. Для конверсии кодов в текст я использовал вот этот конвертор в данные для бейсика. Полученный дамп для инлайн-вставок Паскаля надо немного редактировать (программу не изменить, исходника нет). Позднее на Паскале напишу её вариант, что генерит дамп сразу в формате инлайн-вставки.

В качестве примера для проверки встроенного ассемблера в вашем компиляторе привожу простейшую программку для определения типа процессора. В ней вывод текстов делается как инлайн-процедурой PRINT (менее 10 команд на ассемблере), так и для демонстрации работы @WNC - стандартным паскалевским оператором WRITELN (он намного медленнее и добавляет в код сотню байт). Т.о текст быстрее выводит PRINT или MSSG, зато WRITE позволяет выводить не только текстовые строки, но и десятичные числа (причём с заданным форматом) и даже дробные десятичные числа. PRINT выводит строковые переменные Паскаля (для строк это аналог WRITE), а оператор MSSG выводит ASCIIZ-строки (это строки с завершающим нулём, аналогичные тем строкам, что использует п/п-мма F818).

определение типа процессора:

Рассматривая CP/M-компиляторы, что пригоды для генерации кода КР580, я не упомянул один ЯВУ, который имеет шанс оказаться лучшим, чем Паскаль, а именно Ада, разработанный в начале 80-тых на базе Паскаля (в этом участвовал тот же автор Н.Вирт). Ясно, что переход от Паскаля к Аде несложен, языки лексически похожи. Для нас удачно, что, например, в Суперсофт-Аду встроен ассемблер и код она генерит для КР580. Я уже подумывал ей заняться. Но теперь, когда нет препятствий к использованию ассемблера с Паскалем, в Аде пока нет нужды (глупо метаться между ЯВУ). Позже будет интересно сравнить качество компиляторов Ады и Паскаля, т.к компилятор Ады написан на 3-5 лет позже, возможно он эффективнее.

Кстати, в CP/M кроме бейсика, Си и Паскаля есть ещё несколько компиляторов старых и даже более новых ЯВУ, являющихся производными от Паскаля. А вот от Си ничего производного нет, т.к С++ возник позже, да и похоже объёма ОЗУ 8-ми разрядки для ООП просто не хватило.

В качестве старых ЯВУ для которых есть CP/M-компиляторы можно упомянуть PL/M, PL/1, Алгол и Фортран (не считая много других экзотических ЯВУ). Два последних, это математические языки, они не годятся для работы по железу. PL/M очень близок к ассемблеру и потому как ЯВУ он не очень мощный (хотя до появления КР580-компиляторов Паскаля в 1978, был популярен). Увы, для PL/M есть единственная книга на русском и её не скачать, можно только купить. Совсем древний PL/1 из 1964 немного похож и на PL/M и на Паскаль и скорее всего вполне подойдёт для разработки ПО для РК86. Важно, что литературы по PL/1 больше, чем для PL/M и его компилятор для КР580 кажется лучше, т.к более свежий, чем компилятор PL/M. Как упомянуто ранее, есть несколько CP/M-компиляторов Ада для КР580. Есть и современные кросс-компиляторы языков Ада, Модула-2 и Оберон (они, кстати, Паскаль-производные), но для РК они, увы, не годятся, т.к выдают код для Z80.

И всё же из этих ЯВУ для 8-ми разрядок наиболее удобным для программирования для ретро-ЭВМ следует считать Паскаль МТ+ и два Си, BDS и Aztec. Может они и не самые эффективные, но по ним наибольший объём литературы и документации и большое число примеров, конкретно для данных компиляторов. В частности, для Паскаля МТ+ в 80-тые годы существовала BBS MT+ Users Group, от которой сохранился архив содержащий ~300 исходников программ написанных любителями на Паскале МТ+. Замечу, что примеры от Турбо-Паскаля совсем не годятся, много отличий. Особенно неприятно, что работа с файлами разная.

Хорошая история Паскаля МТ+ вот здесь (там кстати, написано, что компиляция большой программы на дисководе занимала часы, что хоть и преувеличение, но сама идея о тормознутости верна). Там также указано ("Pascal/MT being decidedly superior in most ways to early Turbo Pascal products...), что Паскаль МТ+ лучше, чем Турбо, который вообще можно считать лишь учебной игрушкой. А также, что он лучше, чем BDC C.

Вот для примера использования ассемблера с переходами ещё несколько процедур полезных при разработке программ для РК86.

процедуры только для РК86:


Последний раз редактировалось: barsik (Вс Дек 23 2018, 11:37), всего редактировалось 4 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Практика

Сообщение  san010101 Чт Дек 13 2018, 21:08

9
У меня назрел вопрос, как реализовать все выше сказанное на практике. Имеется Радио 86 РК, как мне начать программировать.
Как сделать , что бы не загружать каждый раз интерпретатор языка программирования,
возможно его перенести в ром диск или ПЗУ, есть у меня устройство SD CARD от Морозова.
Как потом сохранять результаты работы. Может проще пользоватся магнитофоном. Что из себя представляет bios?
В связи с отсутствием в продаже флопи дисков можно ли подключить жесткий диск и есть ли для него ОС?

san010101
Новичок

Сообщения : 41
Дата регистрации : 2018-07-24
Откуда : Красноярск

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Вс Дек 23 2018, 12:55

10
san010101 пишет:У меня назрел вопрос, как реализовать все выше сказанное на практике...
Как сделать, чтобы не загружать каждый раз интерпретатор языка программирования,
возможно его перенести в ром диск или ПЗУ, есть у меня устройство SD CARD от Морозова.
Как потом сохранять результаты работы.
Чтобы использовать транслятор с ЯВУ надо иметь ЭВМ на КР580/Z80 с работающей на ней CP/M или IBM PC на которой работает TSR эмулятор CP/M в которой тоже можно выполнять трансляцию. И как описано выше последнее намного быстрее и удобнее, т.к на PC и редакторы лучше и трансляция в десятки раз быстрее.

А вопрос "чтобы не загружать интерпретатор", - это не ко мне. Потому что я интерпретаторы считаю бесполезными и никогда не использую. Могу посоветовать лишь сделать какую-нибудь апп.доработку по расширению ПЗУ РК (резидентного или в ROM-диске), прошейте туда бейсик, а в монитор включите директиву 'B' для старта бейсика из ПЗУ.

Можно даже заставить бейсик работать из ПЗУ, что позволит использовать бейсик-программу бОльшего объёма. Могу скинуть исходник РК-бейсика, переделайте его для работы прямо из ПЗУ.
san010101 пишет:Что из себя представляет bios?
Вообще под BIOS понимают набор драйверов низкого уровня. Не ясно о каком BIOS-е вопрос.

Выше я упоминал CP/M-BIOS, это один из 3-х модулей CP/M, содержащий драйверы низкого уровня. Ещё есть ROM-BIOS. Это то, что сдуру, с подачи журнала "Радио" называют монитором, который прошит в ПЗУ РК86. ROM-BIOS также содержит процедуры низкого уровня (типа вывод на экран и считывание клавиатуры) и предоставляет программам стандартизованные входные точки в подпрограммы ПЗУ.

В ПЗУ РК кроме ROM-BIOS находится и RAM-монитор обеспечивающий исполнение команд из командной строки. Но RAM-монитор можно без вреда убрать, а подпрограммы ROM-BIOS нет, потому обзывать это ПЗУ монитором неверно.
san010101 пишет:В связи с отсутствием в продаже флопи дисков можно ли подключить жесткий диск и есть ли для него ОС?
Хотя DOS-ов для КР580 меньше, чем для Z80, но всё-же есть. Есть простейшие, размером всего в 2 кб (Хамелеон-DOS А.Мамонтова). Есть РК-DOS, которая написана по мотивам АГАТ-DOS (или Apple-DOS) и даже при модернизации не может поддерживать диски объёмом более 1 мб. Есть ещё пяток самодельных DOS, лишённых прикладного ПО, и есть CP/M, которая поддерживает диски большого размера.

Думаю, что пока для РК ни у кого нет версии CP/M или другой DOS работающей с винчестером. Это делается несложно, просто этим никто не занимался (в силу мизерности объёма ОЗУ в РК). Увы, без расширения ОЗУ к РК можно подключить только совсем примитивные DOS, что не годятся для винчестера (в этих DOS при удалении объём занимаемый удалённым файлом не освобождается) или РК-ДОС, которая пока есть только в версии для РК-КНГМД и для эл.диска из банкового ОЗУ. Остальные DOS требуют расширения ОЗУ, как минимум до 40 кб (нужна добавка как минимум 8 кб, чтобы там могла работать DOS).

У меня есть DOS для ОРИОНА работающая с винчестером. Когда аппаратно сделаю какой-нибудь привод, перетранслирую её для РК86. Достаточно чуть переделать под РК и странслировать под актуальные адреса. Пока для перетрансляции доступны только РК-ДОС и CP/M (другие ОС, чьи исходники есть, - они для Z80, надо переделывать под КР580, а это не быстро).

- - - Добавлено - - -

Если Вы расширите себе ОЗУ на 8 кб, то с удовольствием странслирую Вам вариант РК-ДОС работающий с винчестером IDE. Если надо срочно, то сделаю без проверки в реале, но работать будет. Т.к ничего в заведомо работающем коде не меняется, а я уже делал замену привода в РК-ДОС (и других ДОС) много раз.

Работа по переделке РК-ДОС (или любой другой ОС) работающей с дисководом на винчестер заключается в том, что берётся исходник DOS и в нём строка "include FLOP.INC" заменяется на строку "include VINT.INC". Т.к все модули заведомо исправны, то ошибки не возникнет. Объём кода такой РК-ДОС - 6 кб, потому 8 кб в области A000...BFFF вместо ненужного ППА D14 хватит. Но у меня есть драйвер только для моей схемы контроллера.

Адаптация CP/M на такой объём (в силу особенностей CP/M для архитектуры РК) чуть сложнее, т.к требует несложных доработок (CP/M надо 10 кб, потому имея 8 кб, придётся CCP переместить в основное ОЗУ на 6D00). Но и тут я смогу сделать версию без проверки.

Однако, кроме ОЗУ для винчестера нужен ещё чип-селект. Т.к в базовом РК свободных чип-селектов для расширений не имеется.

Разумнее всего выборку E000...FFFF разделить дешифратором ИД14 (74LS139) на 4 участка по 2К (как в ж.Радио 02.1993), а затем участок F000 делим ещё на 4 участка тем же дешифратором (в ИД14, - два дешифратора, тем он и удобен). Это даст 4 чип-селекта и возможность поставить 4 кб ПЗУ в окне E000...EFFF, как сделано в РК-КНГМД.

Таким образом простой вариант переделки заключается в монтаже одной микросхемы ИД14 вторым этажом и "открытии ОЗУ" в 8 кб на месте запасного ППА D14 в окне A000...BFFF. ОЗУ в окне A000 "открывается" с помощью двух диодов и резистора (или любого вентиля типа ЛИ1, ЛА2...).

Спойлер:
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty Почему нет компилятора PL/M для CP/M-80

Сообщение  barsik Пт Июн 21 2019, 13:55

11
Выше уже упоминалось, что в силу невысоких скоростных характеристик и малого объёма ОЗУ 8-ми разрядок, лучшим по эффективности считается разработанный кем-то в 1972 году язык программирования PL/M. Этот язык использовался в 70-тые годы для программирования микропроцессоров, и даже до середины 80-тых сохранил актуальность для программирования микроконтроллеров. Хотя как инструмент для написания программ для микро-компьютеров PL/M вскоре был вытеснен появившимися в 1978 году (в варианте для микропроцессоров) языками Паскаль и Си, которые предоставляли больший уровень абстракции, и потому в большей степени облегчали программирование.

Как упомянуто выше, многие любители (в т.числе и западные на своих форумах) тщетно искали компилятор PL/M-80 для ОС CP/M (это гуглится). Но найти удавалось только компилятор PL/M-80 для другой ОС по имени ISIS, а также компилятор PL/M-86 для MSDOS.

В XXI-м веке, после того, как был обнародован оригинальный исходник PL/M, появившийся кросс-компилятор PL/M-80 для MSDOS, хоть и неудобно, но позволяет транслировать программы написанные на PL/M для процессора КР580. Потому, в принципе, особой нужды в компиляторе PL/M для ОС CP/M уже нет, хотя встроенная поддержка CP/M-функций была бы полезна.

Язык PL/M исходно был написан на языке Fortran-IV и обычно использовался в виде кросс-компилятора для майн-фрейма. Но он мог быть странслирован и для любой платформы имеющей Fortran-IV, причём и как кросс-средство, так и для работы на самой целевой платформе с родным процессором.

Из-за того, что для написания компилятора был использован развитый мощный ЯВУ, объём кода компилятора PL/M был большим, потому странслированный для 8-ми разрядных платформ (например для ISIS), компилятор был оверлейным (т.е не однофайловым). Потому он мог использоваться только в DOS. Причём из-за того, что владельцем авторских прав была фирма Intel, даже сам разработчик PL/M Гарри Килдэлл не мог сделать и продавать версию PL/M для своей CP/M-80. А фирма INTEL из своих коммерческих интересов выпускала версии PL/M-80 только для ОС ISIS и PL/M-86 для MSDOS.

Т.о мне кажется, что версии компилятора PL/M для CP/M не существовало по следующим причинам.

Во-первых, потому, что компилятор PL/M-80 для CP/M никто не хотел сделать (из-за Copyright принадлежащих INTEL). А во-вторых, это никто не мог сделать. Исходника тогда просто не было. А также потому, что для того, чтобы получить исходник компилятора PL/M для 8-ми разрядки, оригинальный исходник на фортране надо было переработать. Так, как это было сделано фирмой INTEL для ОС ISIS.

Оригинальный исходник компилятора PL/M на Fortrane-IV компилируется в два исполняемых файла PLM81 и PLM82 размером под 60 кб каждый. Точнее такой размер имеют эти файлы странслированные для CPU 8086, для КР580 объём кода был бы лишь на 5% меньше. Потому, если странслировать прямо по этим исходникам версию для CP/M-80, то она просто не сможет работать из-за нехватки ОЗУ для данных, а в большинство реализаций CP/M даже загрузиться в TPA не сможет.

Потому оригинальный исходник PL/M для 8-ми разрядки нуждается в переработке, чтобы компилятор стал оверлейным. Так это и было сделано в версии PL/M для ISIS. Там компилятор разбит не на 2 исполняемых модуля, а состоит из 10 фрагментов. Стартовый файл имеет размер в 7 кб, но в ходе своей работы он подгружает кучу оверлеев, а общий объём кода достигает 125 кб, что примерно соответствует объёму кода двух-файловой кросс версии для процессора 8086.

45 лет назад никто не мог странслировать PL/M для CP/M, просто потому, что никто не имел исходника. В начале XXI-века наконец был опубликован исходник компилятора на Fortran-IV, создающий после его трансляции кросс-компилятор PL/M-80 (неважно для майн-фрейма IBM-360, VAX-20 или IBM PC, в общем для любой машины, где есть Fortran-IV и ОЗУ хотя бы 128 кб). На выходе получаются два файла PLM81 и PLM82 вместе составляющие компилятор.

Но увы, в XXI-м веке среди любителей 8-ми разрядок уже не осталось людей, кто разбирался бы в фортране в нужной степени, а главное, хотел бы это сделать. Просто некому было переписать компилятор в оверлейную версию. И даже, если бы такой энтузиаст нашёлся, то где бы он смог взять CP/M-компилятор Fortranа-IV. Потому и ограничились трансляцией двухфайлового компилятора PL/M-80 в версию для MSDOS.

Потому-то до сих пор никому не удалось найти версию оригинального компилятора PL/M для CP/M. Таким образом, искать для CP/M компилятор Fortran-IV, чтобы странслировать CP/M-версию, - бессмысленно. Во-первых, потому, что компилятора Fortran-IV для 8-ми разрядок скорее всего просто нет (из-за неэффективности фортрана для кода из под фортрана не хватало крошечного ОЗУ 8-ми разрядки), а во-вторых, даже если кому-то удастся переписать исходник, то т.к компилятор написан на ЯВУ, это будет дико тормозной и большой по объёму компилятор.

В 1979 г. Roger Carlson написал компилятор PLMX, слегка улучшенный вариант PL/M-80, причём как раз для ОС CP/M. Он тоже не однофайловый, состоит, как и PL/M для ISIS, из более десятка файлов с общим размером порядка 100 кб.

На выходе PLMX генерит текст на ассемблере - файл с расширением MAC. Этот полученный файл можно странслировать с помощью макроассемблера MAC.COM от Digital Research. Это если PL/M программа одномодульная. Если же программа состоит из нескольких модулей, которые могут быть написаны, как на PL/M, так и на ассемблере, а также и на других ЯВУ (для этого их компилятор должен выдавать REL-файл), то используется RMAC или M80, которые на выходе выдают REL-файл. После чего все REL-файлы линкуются в COM-файл линковщиком.

Т.к недавно я поимел для ИРИШИ CP/M, то уже в ближайшие годы собираюсь освоить программирование для ИРИШИ на PL/M используя этот компилятор PLMX. Естественно, на самой 8-ми разрядке в CP/M или в эмуляторе 8-ми разрядки с CP/M трансляция длится слишком долго. Но если пользоваться TSR эмулятором CP/M для MSDOS, то почти мгновенно трансляцию можно делать на PC в Windows XP.


Последний раз редактировалось: barsik (Ср Авг 07 2019, 14:38), всего редактировалось 1 раз(а)
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Использование ЯВУ для разработки программ для РК86 Empty .

Сообщение  barsik Сб Мар 14 2020, 18:36

12
Классические ЯВУ (т.е те ЯВУ, что сделаны по Кернигану-Ритчи или Вирту) немного сложнее, чем ассемблер. Ассемблер проще. Точнее, чтобы писать на ЯВУ сначала надо запомнить в несколько раз бОльший объём информации, чем для ассемблера и затем необходимо опытным путём усвоить нюансы и запомнить лексику (соответственно Си или Паскаля). Потому на ассемблере (особенно  в мнемонике Z80) сразу же может писать любой, лишь вчера узнавший о работе команд процессора, а чтобы "въехать" программирование в ЯВУ, надо, как минимум, несколько недель изучать документацию и обязательно осваивать ЯВУ на практике.

Зато, чтобы что-то писать на ассемблере, нужно иметь намного больше энтузиазма, т.к это менее интересно, нудно и тратится больше времени. Я за последние 6 лет не написал на ассемблере ничего, хотя до того писал на ассемблере Z80 много. Более-менее приличные разработки на ассемблере отнимают от 50 до 500 часов чистого времени. Сейчас мало кто может позволить себе это, да и энтузиазм на столь долгий срок не сохранить.

Потому сейчас разумнее попробовать хорошо освоить какой-либо ретро ЯВУ, хотя-бы даже бейсик (естественно, компилятор, не интерпретатор). Исходя из этого я и собирался с целью оценки посмотреть на PL/M (что и успешно сделал), кстати, затем выяснилось, что и на PL/I стоит взглянуть (т.к обнаружилось, что Г.Килдэлл считал его лучшим компилятором для КР580).

PL/M из всех ЯВУ даёт максимально плотный код, но по половине операторов он лишь препроцессор ассемблера и в итоге имеет самый низкий уровень самого языка, да и лексика его неудачна. На PL/M можно делать процедуры низкого уровня для более мощного ЯВУ. Простенькие модули размером не более 100-150 строк для внешних процедур вполне удобно писать на PL/M (чтобы не связываться с ассемблером). Но сложную основную программу удобнее писать и отлаживать на более мощном ЯВУ. Время потраченное на разработку и удобство программиста важнее, чем плотность кода и его быстродействие, т.к при нужде ОЗУ можно аппаратно добавить, а у CPU увеличить такт.

После краха винта и потери предыдущих наработок, как по Паскалю, так и по PLMX, у меня пропало всякое желание осваивать PL/I. Лексика PL/I, похожая на лексику PL/M, отвращает, а непопулярность, сложность и отсутствие учебников также не способствуют его привлекательности. А то, что не нравится, даже под давлением логики и здравого смысла, пытаться осваивать бесполезно, это заведомо обречено.

Для КР580 выбор мощных компиляторов меньший, чем для Z80. Не считая малопригодный для людей бейсик, это - Ада, Паскаль или Си. Ада (являющаяся развитием Паскаля) имеет хорошие компиляторы, но по ней я пока не нашёл учебников. В середине 80-тых годов на 8-ми разрядках более качественная Ада как раз начала успешно вытеснять господствующий тогда Паскаль (и менее популярный тогда, Си). Но тут неожиданно сами 8-ми разрядки вышли из моды. Компиляторы Си для КР580 считаются слабыми и глюкастыми, а общепризнанные хорошими компиляторы требуют Z80. А, т.к Паскаль имея родство с бейсиком, осваивается легче, чем Си (тем более, что Паскаль и без того большинство молодых людей уже знают, т.к изучили ещё в школе), а Паскаль МТ+ имеет к тому же очень хорошую документацию, то ясно, что выгоднее всего в качестве ЯВУ осваивать Паскаль МТ+ или Турбо-Паскаль.

Как упомянуто ранее, ЯВУ как раз для медленной текстовой машины оправдан. Т.к для текстовых игр без панорамирования (т.е без сдвижки всего экрана) даже у РК есть несколько-кратный запас скорости (в частности, при смене констант торможения всеми ценимые эркашные XONIX и PACMAN прогонялись нормально при такте всего 250 КГЦ).

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

Для меня это интересно лишь в плане проверки этой мысли, а сам РК86 - конечно не интересен. По причине отстутствия графики. Это как раз и мешает разработать для РК86 версии игр "DOOM" и "Принц Персии". Но на этапе изучения, освоения, разработки инструментария для последующего использования этого опыта уже для 8-ми разрядки с графикой, РК86 вполне удобен.

Т.к на РК вывод на экран это всего одна команда ассемблера, в то время как, чтобы вывести тот же символ на Специалисте нужно прогнать сотню команд процессора. В принципе, если бы в РК увеличить быстродействие в 4 раза, ввести в фонт 1024 тайла для вывода спрайтов и пейзажа, то такой РК предоставлял бы программисту даже лучшие возможности для игр, чем графические компьютеры Вектор, Специалист или ОРИОН.

Потому неделю назад я вернулся к освоению Паскаля МТ+. Почитал документацию, восстановил набор подпрограмм для ввода/вывода на компьютере без CP/M, вспомнил использование операторов Паскаля. А т.к мне приятнее использовать версию Паскаль МТ+ от ОРИОНА в котором сообщения русифицированы в КОИ-8, то транслировал и проверял в эмуляторе ОРИОНА для MSDOS, т.к в чужих эмуляторах по времени получается дольше из-за меньшего удобства работы с дисками CP/M (эмуляторы под Windows удобнее лишь для запуска МГ-программ). Т.е использовал хотя и русифицированную, но более старую и частично дохлую версию 5.5 из 1982 года, а не последнюю безошибочную версию 5.61 из 1984 года. Возможность иметь INLINE-ассемблер меня не волнует, т.к я нашёл транслятор ассемблера в ERL-формат (ASMMT), благодаря которому исчезла всякая проблема интерфейса с ассемблером и неприятное неудобство из-за непривычной людям мнемоники КР580 в INLINE-вставках.

Но как раз из-за использования старой версии компилятора мне удалось обнаружить способ позволяющий вставлять INLINE-ассемблерные команды с переходами даже на старой версии Паскаля МТ+. Оказалось, если ассемблерную команду раздробить на байты, т.е вставлять адрес перехода в код JMP-команды отдельным INLINE оператором, то удаётся получить верно транслируемый ассемблерный код с переходами.

Вот как положено делать переходы в ассемблерных вставках, т.е именно так и должен работать компилятор с INLINE, и так он и работает в исправных версиях 5.2 и 5.61 (в точном соответствии с документацией):


procedure prtstr(var str: string);
type    ukchar= ^char;
var     adr: ukchar;
begin
  adr:=addr(str);
  inline( "LHLD/ adr/
          "MOV B,M/
          "INX H/
          "MOV A,M/            { -9 }
          "ORA A/              { -8 }
          "RZ/                 { -7 }
          "MOV C,A/            { -6 }
          "CALL/ $F809/        { -5 }
          "INX H/              { -2 }
          "DCR B/              { -1 }
          "JNZ/ *-9 );
end;


Но в версии 5.5 Паскаля МТ+, что как раз и имел хождение в СССР, так почему-то не работает, - компилятор ругается, выдаёт ошибку на сам символ '*'. Но пытаясь делать "химию" (т.е вычисляя и подставляя адреса вручную), случайно открыл вот такой способ странслировать адреса переходов правильно и в этой дохлой версии. Оказалось, что если символ '*' стоит в отдельном операторе INLINE, то генерится верный адрес перехода. Вот работающий аналог той же самой ассемблерной INLINE процедуры, но уже для глюкастой версии 5.5:


procedure prtstr(var str: string);
type    ukchar= ^char;
var     adr: ukchar;
begin
  adr:=addr(str);
  inline( "LHLD/ adr/
          "MOV B,M/
          "INX H/
          "MOV A,M/            { -9 }
          "ORA A/              { -8 }
          "RZ/                 { -7 }
          "MOV C,A/            { -6 }
          "CALL/ $F809/        { -5 }
          "INX H/              { -2 }
          "DCR B/              { -1 }
          "JNZ );              {  0 }
  inline(  *-9 );
end;


Отличие - только в предпоследней строке. Да, кстати, это реальная (и полезная ретро-пасквилянтам программирующим для 8-ми разрядок с ПЗУ как у РК86, Специалиста или ОРИОНА) процедура - аналог стандартной РК-подпрограммы $F818, но работающая в Паскале. Проблема стандартной подпрограммы $F818 в том, что она рассчитана на обслуживание Си-программ, т.е выводит, так называемые, ASCIIZ-строки. А в Паскале тексты задаются совсем иначе, - Паскаль-строками. Которые характерны тем, что не имеют стоп-байта в конце строки символов. Вместо этого первым байтом хранится реальная длина строки. А авторы Микро-80 и вслед за ними все остальные изобретатели самодельных 8-ми разрядок сдуру не включили такую нужную людям подпрограмму в ПЗУ компьютера.

Не имея такой процедуры для вывода Паскаль-строк, чтобы выводить тексты из Паскаля в машине без CP/M программисту приходится извращаться. Для этого приходится делать следующее. Функцией LENGTH вычисляем длину строки. Эту длину (плюс ещё одну единицу) прибавляем к адресу начала строки, которую вычисляем функцией ADDR. Так мы вычисляем адрес байта за концом текста. И туда записываем стоп-байт 0. И только после этого (причём ещё прибавив к адресу начала строки единицу, чтобы пропустить байт числа символов и в итоге получился бы адрес первого символа строки) можно загрузить его в регистр HL и сделать CALL F818.

Маленькие процедурки, если Вас не тошнит от мнемоники КР580, можно писать и в INLINE-ассемблере. Но всё-равно при этом получается проигрыш в объёме кода, т.к передача параметров в ячейках ОЗУ менее выгодна по объёму кода и скорости, чем через стек (что делается при целиком реализованной на ассемблере внешней процедуре).

Вот та же процедура вывода Паскаль-строки (здесь она названа MSSG) реализованная в ASM-модуле. В ASM-модуле вывод символов для ускорения делается с помощью RST 10 (для чего 3 байта команды JMP SCOUTA загружаются на адрес 0010 процедурой INIRST, что выполняется при старте программы). RST кроме 0-вого можно использовать, т.к Паскаль программа транслируется на адрес 0100 (а CP/M тоже другие RST, кроме 0-вого не использует). Ассемблер позволяет ввести многие полезные функции, исходно отсутствующие в Паскале. Например, в бейсике есть функция USR, позволяющая вызывать ASM-подпрограммы ROM-BIOS (передаёт в подпрограмму один параметр и из неё принимает также один параметр). В этом же ASM-фрагменте показано как ввести в Паскаль МТ+ аналогичную функцию CALL.

Спойлер:

Кстати, на архивных сайтах версия МТ-Паскаля 5.5 есть в двух вариантах - "просто 5.5" и "5.5 Wavemate". Так вот версия "просто 5.5" на некоторых совершенно нормальных программах выдаёт ошибку "Деление на 0". А вот при версии "5.5 Wavemate" - всё отлично транслируется (если не зацикливаться и не считать проблемой необходимость вставлять отдельный оператор INLINE для адреса перехода в ассемблерных вставках). Хотя (т.к я сейчас транслирую не в CP/M, а в Windows XP) ошибка может быть из-за неточной эмуляции CP/M в MSDOS.

Трансляция в Windows XP длится доли секунды, но и в реале компилятор Паскаля компилирует раз в 10 быстрее, чем компилятор PL/M (потому что Паскаль сразу создаёт REL-файл, а PL/M только выдаёт исходник на ассемблере, который ещё надо транслировать ассемблером). Информация по ошибкам трансляции также в Паскале МТ+ лучше, чем в PL/M. Но зато исходник на ассемблере предоставляемый PL/M-ом удобнее, т.к он в абсолютных адресах. А Паскаль МТ в ходе трансляции не создаёт исходника, чтобы его получить запускается дизассемблер, который и создаёт ASM-файл в котором в ассемблерных INLINE вставках менее удобно разбираться.

Кстати, если бы для MSDOS был бы драйвер VT52.SYS (читал, что он существовал в 80-тые годы), то и запускать, проверять чисто текстовые программы для 8-ми разрядки можно было бы прямо в MSDOS. Хотя и без VT52.SYS тоже можно (но уже не пригодные для РК-версии, а с другими искейп-кодами), - если использовать драйвер ANSI.SYS, в нём есть возможность включать инверсию и позиционировать курсор искейп-кодом.

Так, что теперь ничего не мешает фанатам Специалиста начать писать "DOOM" для него. Паскаль МТ+, как раз позволяет оверлеи программы запускать в другой банке памяти. Т.е, если в Специалист ввести коммутацию банок ОЗУ участком в 32 кб (чтобы экран оставался на месте), то полностью снимается ограничение на объём кода. Т.о объём кода программы наращивается без ограничений. Быстродействие тоже не проблема поднять в два, три или даже четыре раза, если применить скоростной процессор Z80H.

Сегодня написал редактор фонтов для РК86. А для дурной псевдографики РК, что довольно сложна, как раз выгоден именно ЯВУ, несмотря на потерю быстродействия относительно ассемблера. Предполагая, что в дальнейшем увеличив размер матрицы до 16*16 и 24*24 пикселей это превратится почти в редактор спрайтов (останется дополнить выводом в динамике, т.е последовательным выводом спрайтов с периодом их смены 4-6 раз в секунду, что создаёт эффект мультипликации и позволяет увидеть движения).

Чтобы отлаживать программу РК86 с прямой записью в экран не на самом РК86, а на ОРИОНЕ, пришлось написать процедуру вывода на экран ОРИОНА: подлежащие выводу символы не только специальной процедурой заносятся напрямую в экран РК (на 76D0...7FF4), но, чтобы на экране ОРИОНА была картинка, эти символы выводятся одновременно на экран ОРИОНА, причём этот экран ОРИОНА вообще находится в другой банке ОЗУ (т.к эта отлаживаемая программа РК запущена в CP/M ОРИОНА c TPA 54К, которая из-за неудачной архитектуры ОРИОНА вынужденно работает в банке 1, где в монохроме экран не мешает).

Кстати, несколько слов о перспективах прогона на ОРИОНЕ программ РК86 в оригинале.

Спойлер:

- - - Добавлено - - -

Стал пользоваться компилятором Паскаль МТ+ версии 5.61, в котором INLINE работает без проблем и обнаружил ещё одно отличие работы INLINE в этой версии от предыдущих версий. В предыдущих версиях команды ассемблера в INLINE можно было писать как большими (заглавными) буквами, так маленькими. А вот компилятор 5.61 почему-то любит, чтобы мнемоники ассемблера были написаны большими (заглавными) буквами, иначе выдаёт ошибку "Недопустимый аргумент в операторе INLINE".

Обычно я и так пишу ассемблерные тексты большими буквами (т.к зрение у меня всего одно, стараюсь его беречь избегая крошечных букв, от которых зрение излишне утомляется), но некоторые пишут ассемблерные тексты мелкими буквами. Вот им придётся при написании INLINE вставок в Паскаль-программах поменять эту вредную привычку. Кстати, в мнемониках КР580 пробелы и запятые можно не писать, т.е годится PUSHB, MOVCA.

В один из дистрибутивов из СССР входит компилятор ассемблера ASMMT.COM. Это тот же Microsoft ассемблер М80, но чуть изменённый. Он транслирует сразу в ERL-файл. Возможно, что изменено только расширение выходного файла. Потому что, если ASM-модуль странслировать с помощью обычного М80 и переименовать расширение выходного файла в ERL, то это тоже без проблем прилинковывается к основной Паскаль-программе с помощью LINKMT.

Вообще на Паскале МТ+ на самом Паскале программировать несколько сложнее и неудобнее, чем на Турбо-Паскале, т.к МТ+ реализует только классический Паскаль, а в Турбо-Паскаль добавлены удобные расширения, без которых программировать менее удобно (иногда приходится извращаться или выходить из положения с помощью ассеблера). Но этот недостаток компенсируется тем, что МТ+ допускает линковку с ассемблерным (или даже с полученным из под чуждого Паскалю ЯВУ) REL-модулем, а Турбо-Паскаль заставляет всё делать на самом Паскале, а небольшие ассемблерные вставки возможны только в виде INLINE и их добавлять гораздо утомительнее.

Модульность тоже накладывает ограничения. Так функция ADDR выдаёт адрес относительно начала модуля, а не от начала программы. Потому, например, когда переменная, Паскаль-процедура или ASM-подпрограмма не в MAIN-модуле, то мы не можем ни в одном из модулей узнать их адрес (требуется извращаться складывая вручную размеры предыдущих модулей с оффсетом). Передаваемые внешним процедурам/функциям параметры и возвращаемые назад результаты лучше иметь не байтовыми (т.е byte/char), а 16-ти разрядными, т.к тогда на каждой процедуре и функции экономится более 10 байтов (это видимо потому, что параметры в Паскале передаются в стеке, а он у процессора КР580 - 16-ти разрядный, потому при передаче байтами, тратится доп.код на обнуление старшего байта слова).
barsik
barsik
Ветеран

Сообщения : 1032
Дата регистрации : 2016-11-10
Откуда : Россия

Вернуться к началу Перейти вниз

Вернуться к началу

- Похожие темы

 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения