ZX Evolurion - это девборда, она как пустое ведро - можно залить и коньяк, и мочу
СР/М выбросили потому, что идеология развития НедоАТМ претерпела изменения относительно идеологии развития компьютера АТМ, который был разработан именно как CP/M компьютер.
psb, свежо предание, но верится с трудом, обычно от тебя исходит токо троллинг.
Вызов всех процедур ядра через диспетчер (0008h) осуществляется с передачей параметров (и результата) в регистрах. Разве нет?
И правильно, от стека в системных вызовах С надо уходить для многостраничного ПК, т.к. при вызове стек вызывающей программы останется в другой странице. В uzix 1.x все программы работали в одной и той же странице (из-за чего и медленно - их приходится постоянно отгружать в свап). Что в принципе позволяло использовать стек для вызовов ядра, но там все же используется передача данных в регистрах.
Спасибо, кэп. (с)
Вообщето я так и делал в CP/M, правда на Орионе. И пересылки, и длинный вызов из которого можно было обычным RET возвращаться между страницами. Проблема в том, что это все медленно работает. "Длинные" CALL и RET получаются непростыми (а следовательно медленными) подпрограммами - там многое надо учитывать: автоопределение и сохранение на стеке страницы откуда вызов, определение и сохранение на стеке состояния диспетчеров памяти (т.к. вызываемая п\п может их портить и в итоге RET получится не туда куда надо), куски для обслуги прерываний - чтобы если случится прерывание, ЦПУ по прерыванию попал в нужную страницу - туда где обработчик - а не в ту, где ты ковыряешься в текущий момент. И по RETI вернулся обратно из обработчика прерывания - опять же межстранично. И т.д.
В итоге, CP/M, где у меня все вызовы BDOS/BIOS были векторизированы на межбанковских процедурах, и "прозрачная" для прерываний (что позволяло писать драйвер любого устройства и централизованно размещать его в любой странице памяти, эмулировать "многозадачность") получилась в 2 раза более медленной, чем ее одностраничный брат. На что мне тут же указали (еще тогда, в 90-х), не помог никакой "новый сервис ОС"
Последний раз редактировалось Error404; 26.07.2011 в 10:14.
Лучше сделать и жалеть, чем не сделать и жалеть.
Некоторые из моих поделок тут: https://github.com/serge-404
я незнаю как на орионе, но относительно профи "дальние" вызовы особых проблем не имеют. конечно, есть потеря скорости, однако не критично, особенно если учесть факт наличия турбы. на профи все дрова или их большая часть сидит в 5й странице. особо не замечал каких-либо проблем или тормозов при их вызове. кроме того, дабы избежать потери данных со стека оставшегося в другой странице, никто не мешает переставить стэк в окно, которое не участвует в переключениях страниц. тем более если требуется передать какие либо короткие ответы от функции. несколько байт можно и переставить, разве нет?
а тормознутость юзикса объясняется ещё и тем, что во1х, ты посмотри на библиотечные вызова, тот же fopen, насколько он прожорлив и здоровый. printf и другие. очень много ляпов в системе и лишних условий, которые можно или сократить, упростить или развернуть. а второй юзикс, согласно переписке с автором, большей частью написана с преминением вставок ассемблера. там даже один и тот же файл (программа) занимает меньше места, чем у первого юзикса.
к сожалению не всех.Вызов всех процедур libc через диспетчер (0008h) осуществляется с передачей параметров (и результата) в регистрах
а если говорить непосредственно про библиотечные вызовы, то они диспечер то вобщем и не используют, за редким исключением когда делают вызовы типа открытия файла/потока и подобное. а вот возврат как раз в регистрах:Код:asm(" psect text,class=CODE"); asm(" global __sys__3"); asm(" global _mount"); asm(" signat _mount,12346"); asm("_mount:"); asm(" pop hl"); asm(" ex (sp),hl"); asm(" push hl"); asm(" ld hl,19"); asm(" jp __sys__3"); ... asm("__sys__3:"); asm(" push bc"); /* the third value is already in stack */ asm(" push de"); asm(" push hl"); dosyscall(); ... #define dosyscall() asm(" call " __str1(SYSCADDR)) ... #define SYSCADDR 8 /* System call routine */
* System call structure:
* Arguments passed through stack: unix(#,arg1, arg2, ...)
* Result returned in DE:HL (LSB/MSB form)
* If error found then CY=1 and BC=errno
Мой тебе совет - забей с либами для ZX-a, и линкуй "руками" сразу компилируя под фиксированные адреса.
Потому-что:
1. либы сохраняют место на диске (но по факту сейчас нет проблем с нехваткой места на диске);
2. либы сохраняют место в памяти (но только если система может грузить сразу более одного приложения, по факту для классического спекки это не актуально);
3. либы могут настраиваться на адреса куда они загруженны и позволять делать всякие трюки с релокацией для управления свободной памятью (это для спекки не актуально изза того что алгоритм автоматического распределения памяти сам по себе требует кучу места для для своих кода и данных, короче для спекки он сильно жирный);
4. либы можно поставлять в бинарнике и просто использовать не парясь с компиляцией (это типа удобно но имея либу в исходнике можно ее подхачить легко что более важно!)
ну и это еще не все... это так на вскидку написал
Для большего понимания предложенной мной архитектуры проги я тут примерно интерфейс kernel-a выложу:
/* тут лежит номер текущей, включенной в адресное пространство страницы
в системных переменных басика 128 есть этот байт можно его использовать */
BYTE currenPageNumber;
/* эта функция должна: включить pageNumber, провести операцию обмена содежанием
между областями памяти address1 и address2 длинна блока lenght, включить обратно
currenPageNumber */
void swapDataBlock(BYTE pageNumber, SHORT address1, SHORT address2, SHORT lenght);
/*эта фукция для перехода на код в другой странице, включает pageNumber, обновляет
currenPageNumber, делает jp на address1*/
void jmpFar(BYTE pageNumber, SHORT address1);
/*эта функция для call-a на код в другой странице, включает pageNumber, обновляет
currenPageNumber но сохраняет старое значение у себя на стеке, делает call на address1
по возврату ставит старое значение pageNumber и делает ret*/
void callFar(BYTE pageNumber, SHORT address1);
/*это обработчик int-a, запрещает прерывания, включает нужную сраницу где находится код обработки прерывания но сохраняет старое значение на стеке, вызывает обработчик, после возврата высталяет старый pageNumber разрешает прерывания делает reti*/
void intHandler();
Последний раз редактировалось bigral; 26.07.2011 в 12:02.
Не получится, либа Сишная, прога на асме. У меня щас примерно так и сделано, под фиксированные адреса, но чуть Си код подправишь и надо EQU'шки в проге обновлять. Не очень интересно.Мой тебе совет - забей с либами для ZX-a, и линкуй "руками" сразу компилируя под фиксированные адреса.
А я бы обёрточку асмовскою в Си код вставил и ноу проблем. Перемещаемый код мне не нужен. Тока пока немогу определится как будет удобней к ней обращатся.
Аргументы через стек передаю. Либу пока цепляю во 2-3 банки, но скорей всего скомпилю в 0-1, потому что уже некоторые неудобства ощущаются с предачей аргументов. Дальше хуже скорей всего будет.
Последний раз редактировалось DimkaM; 28.07.2011 в 22:04.
alone, я конечно дико извеняюсь но вообще можешь по проще объяснить чтоб даже я понял (и тем более ААА), ато у Вас у гуру типа тебя и Роб.Ф-а вообще "марсианский" язык какой-то. Мне вот интересно друг друга вы понимаете? Прикольно было бы попросить Роб.Ф-а чтоб он это расшифровал...
Что конкретно непонятно?
куда указывают hl и de вначале? что собой представляет часть софта которая имеет в себе вызываемые функции? что ожидалось в результате выполнения этого куска? и самое главное как это решает концептуальную проблему - "работа с данными в странице которая не подключенна в адресное пространство" ?
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)