Не говорю что специально. Да и вообще не вижу ничего зазорного в переносе хороших идей с/на спек.Цитата:
Сообщение от Shaos
Основываюсь на словах тов.yoko_ono и acidrain, говорящих что это есть "как в амиге".
Вид для печати
Не говорю что специально. Да и вообще не вижу ничего зазорного в переносе хороших идей с/на спек.Цитата:
Сообщение от Shaos
Основываюсь на словах тов.yoko_ono и acidrain, говорящих что это есть "как в амиге".
Попробуем сформулировать тезисы по результатам темы:
1. Подход библиотек Амиги - это тормоза ООП без преимуществ ООП.
2. Для Speccy лучше всего подход с пропатчиванием CALL клиента.
3. Косвенные переходы следует использовать для полиморфизма.
видимо мы читали разные книги...Цитата:
Сообщение от captain cobalt
в моих книгах ООП=наследование+инкапсуля ция+полиморфизм. и соответсвенно "неявный" вызов возможен только для явных потомков. в случае фара этим даже не пахнет.Цитата:
Сообщение от captain cobalt
фар определяет и использует плагины на основании списка функций, это не ООП. это ближе всего к duck typing которая активно используется в новомодных языках (python, ruby)
тогда уж:
#include "stdio.h"
printf(...)
тоже ООП :) такая программа могла быть написана много лет назад, а работает до сих пор с новыми версиямя libc. причем за годы существования проги libc могла поменяться очень сильно включая новую функциональность
пять пунктов ничем не пропитано :) я описал те проблемы которые динамическая загрузка библиотек имеет на текущий момент для спека. а уж про то что для динамической компоновки обязательно нужна ось я точно не говорил :) если Вы говорите что ООП данные ограничения/проблемы позволяет обойти то я удовольствием послушаю какЦитата:
Сообщение от captain cobalt
вот только объяснение про "сферический компоновщик в вакуме" это не объяснение. это демагогия на мой взгляд. потому что:Цитата:
Сообщение от captain cobalt
1. кто компоновщика будет загружать?
2. кто ему расскажет что нужно грузить?
так и хочется запретить книги про ООП :(
где в амижном подходе ооп? где там наследование и инкапсуляция? какие такие тормоза?Цитата:
Сообщение от captain cobalt
какой на*рен полиморфизм на спекке? вызов функции по таблице - это не полиморфизмЦитата:
Сообщение от captain cobalt
ребята, ну давайте не будем бросаться терминами! особенно если они не однозначные и все их понимают по-своему. а уж если ругаем чего-нибудь, то хотя бы с аргументами
перечитайте пожалуйста мое исходное сообщение. EXE не патчится и либа кстати тоже.Цитата:
Сообщение от yoko_ono
1. в заголовке exe файла находится список jmp'ов
2. все call'ы идут на них
3. когда система загрузит exe+dll она исправляет адреса в этих JMP'ах. ни один байт внутри программы не изменяется!
если я плохо объясняю, то посмотрите в MSDN он в отличии от амижных доков находиться в открытом доступе.
более того, если dll без base relocation (т.е. грузиться по фиксированным адресам) то внутри exe все call'ы идут сразу в библиотеку без дополнительного jmp'а. причем все это делает линкер автоматом при сборке программы, руками делать ничего не надо
Имеется в виду, что ООП тормоза, но есть и преимущества, а подход амиги- тормоза (как и в ООП), но нет преимуществ, перевешивающих тормоза.Цитата:
Сообщение от elf/2
Не надо %) ООП это хорошо (при правильном использовании конечно).Цитата:
Сообщение от elf/2
Если уж говорить о полиморфизме в применении к плагинам, то делают так, как я рассказал ранее- экспортируется одна-единственная функция фабрики классов, которая инстанциирует потомки класса-интерфейса. А вот при вызове уже чистый полиморфизм получается.
Вернусь к теме разговора. Для чего все начинал? У меня есть моя та самая библиотека модулей. Я ее планирую применить в некоторых своих проектах. В то же время, не вредно помечтать (см. первый пост). Если народ хочет поддержать идею, то я жду предложений по расширению функциональность (изменять глобально там вроде ничего не надо). А если не надо- то не надо... Буду делать исключительно для себя, для своих целей
Это не ООП. Это только тормоза ООП. Без наследования и инкапсуляции.Цитата:
Сообщение от elf/2
Тормоза на загрузку хэндла в регистр, косвеную передачу управления, и недоступность регистра для передачи аргументов.
Те же самые тормоза, что у вызова виртуальной функции.
Но если полиморфизм - это силища ого-го :) , то у Амиги "просто библиотеки". :)
Зато полиморфизм - это (часто и помимо прочего) вызов функции по таблице.Цитата:
Сообщение от elf/2
Хорошо. Всегда готов. ;)Цитата:
Сообщение от elf/2
Это правильно. Но это всего-лишь определение ООП. Если пользоваться только определением, ничего хорошего не получится.Цитата:
Сообщение от elf/2
Если прочитать определение поэзии, то сразу после этого не станут сразу получаться хорошие стихи. :)
Если взять из матанализа определение предела функции в точке, то вычислить даже один предел довольно затруднительно. К счастью, для этого имеются гораздо более сподручные средства, такие как "Правило Лопиталя", "Теорема Коши" и ещё вагон всяких разных, которые напрямую не следуют из определения предела.
Как грамотно писать ООП программы. На этот вопрос нет ответа в книгах типа "ООП=наследование+инкапсул� �ция+полиморфизм". Это всё равно что обучать искусству поэзии по принципу: "поэзия - это <...тут определение поэзии...>; вот, например, Пушкин: <...здесь стихи Пушкина...>".
Как же всё-таки проектировать ООП программы? Об этом рассказывается совсем в других книгах. И обсуждается это не скатываясь на определения.
ООП - это неявное использование функциональности.Цитата:
Сообщение от elf/2
Неявное использование функциональности - это не всегда ООП. Но оно всегда может быть выражено в ООП. А раз может, то, по мнению членов "секты ООП", оно должно быть выражено именно так. :)
Как же выразить плагины в ООП? Очень просто: все плагины должны наследовать от одного абстрактного класса плагина.
Всё очено просто: клиенты базового класса могут динамически компоноваться с реализациями производных классов.Цитата:
Сообщение от elf/2
Это не имеет значения.Цитата:
Сообщение от elf/2
Его можно загрузить из boot.B, его можно прошить в ПЗУ. Много чего можно.
Но коль скоро динамический компоновщик загружен в память, он может сидеть там сколь угодно долго. :) И динамически компоновать сколь угодно много. :)
А это не его дело что-либо грузить. :) Его дело компоновать то что ему дают. :) Откуда загрузилось то что ему дают компоновать - это тоже не его дело. :)Цитата:
Сообщение от elf/2
Кто же будет грузить то что надо компоновать? Грузить может, например, #3D13, который всегда доступен.
Но кто же будет говорить #3D13, что надо грузить? Что ж. Придётся написать маленькую программу, которая будет делать это. С пользовательским интерфейсом. И назвать её "файловый менеджер". :) Более того, поскольку есть динамический компоновщик, то можно скомпоноваться с (собственноручно загруженным) драйвером HDD, а затем грузить модули с HDD.
По функциональности уже ОСь получается, хотя казалось бы, динамический компоновщик... ;)
Здесь нужно уточнить, что на x86 команды прямых CALL и JMP - относительные. Относительно счётчика команд. Если код использует внутри себя только такие переходы, то он перемещаем без пропатчивания.Цитата:
Сообщение от elf/2
Вот такие предложения:Цитата:
Сообщение от Vitamin
1. Динамический компоновщик и библиотеки должны оставаться в памяти как можно дольше без лишних повторных загрузок с диска. Тогда и ось сможет "нарасти".
2. Нужен контроль целостности. Например, на основе строки с перечислением аргументов. Если импортированный и экспортированный интерфейс не совпадают, нужно сообщение об ошибке.
3. Нужна единообразная инструментальная поддержка для статической и динамической компоновки. Чтобы из одних и тех же исходников можно было компоновать как динамически так и статически.
4. Нужно составить список библиотек, которые нужны человечеству. С описанием что они должны делать.
Примерно этого я и ждал вот уже 13 страниц %))
Я еще не заглядываю в такие далекие дебри как динамическая компоновка. У меня (по смыслу) статически-динамическая: динамическая в смысле что все подгружается при старте, а статическая в смысле что все настраивается за кадром и программа знать не знает что ее собрали из кусочков.Цитата:
Сообщение от captain cobalt
Ну простейший контроль само собой- если в собранной программе остались неразрешенными некоторые внешние ссылки, она считается невалидной. Равно как и если есть две и более точки с одним и тем же именем (для универсальности- сигнатурой). Плюс конечно версионный контрольЦитата:
Сообщение от captain cobalt
Это уже тонкости, их реализация осущствляется автоматически при правильном выборе функционала и механизма реализации релокации и интерфейсов.Цитата:
Сообщение от captain cobalt
Ну простейшее- математика, графика, дисковые операции. А в дальнейшем- каждый может писать свои и выкладывать их.Цитата:
Сообщение от captain cobalt
вот и я о том же :) либо компоновщик - часть "оси", либо статически слинкован с программойЦитата:
Сообщение от captain cobalt
а про ООП в этом треде надо завязывать, imho. пока нет языка с явной поддержкой по крайней мере...
да и вообще сравнивать ООП с библиотеками - не корректно. т.к. лежат они на совершенно разных уровнях.
одна беда в этом треде: слишком все эмоционально, и надо бы его уже на два-три делить
1. статическая линковка из объектников (Витамин предложил): как это сделать на спекки оптимально
2. динамическая линковка: изложить и сравнить существующие подходы (амми/libman/Win/Lin/etc.) и в результате выбрать/синтезировать то что для спека лучше подходит
3. ооп и иже с ним (лучше сразу во флейм)
Ребят, а на самом деле - стоит ли оно того?
Посмотрим еще раз на плюсы:
1) экономия места. Но кого оно волнует из эмуляторщиков (а их большинство)? Да и реальщики стараются подрубить винт или флешку.
2) исправление ошибки в библиотеке устраняет оную во всех зависимых программах.
Но как правильно было замечено, (2) одновременно ведет и к гораздо бОльшей проблеме, то что в винде было названо DLL-hell. Ладно там ошибку исправить, а как быть, когда в результате эволюции наступает этап, когда требуется изменение интерфейса функции? Ресурсы спектрума уж очень скромны, чтобы решать такие задачи, где даже у старших братье все до сих пор не все гладко.
И еще. В спектрум-среде за все это время как-то не сложилась практика использования общих библиотек, думаете когда сообщество стало гораздо менее многочисленным есть еще шансы?
Частично проблемы общих библиотек решаются с появление нормальной ОСи. Ведь тогда ввод-вывод уже будет поддержан ядром, а это основное, где могут присутствовать обшие куски. Второе - UI-core - но его почти всегда каждый предпочитает делать по-своему.
Имхо, гибкий инстурмент подключения библиотек во время компоновки был бы более уместен. Кстати, в CP/M такое было. В том числе там можно было подключить из бибилиотеки к модулю прямо конкретную функцию, а не всю либу.
Как только что показано, загрузка и компоновка - это разные вещи.Цитата:
Сообщение от Vitamin
Сборка в момент загрузки - это динамическая компоновка.
Держать библиотеки в памяти наиболее полезно для разработки.
Сейчас для сборки используются include. В однотекстовых ассемблерах при каждой сборке происходит елозенье по диску. В многотекстовых, когда всё в памяти, всё равно имеются тормоза с компиляцией. Если же всё лежит в памяти готовое к употреблению, нужно лишь при компиляции прилинковать один разрабатываемый модуль.
Вот.Цитата:
Сообщение от Vitamin
Сигнатура это хорошо и обязательно.
Проблема такая.Цитата:
Сообщение от Vitamin
Есть "старая добрая статическая" сборка через include. Есть "новая крутая динамическая". :)
Программист смотрит. Если инструментарий отличается, нужно выбирать что использовать. Для старого способа уже есть свой наработанный код. Для нового способа надо переписывать, переделывать почти с нуля. Многие не смогут разобраться в своих собственных старых ассемблерных исходниках. :)
Если возможна постепенная миграция, то больше программистов будет разрабатывать универсальный код. Поначалу он будет использоваться со статической компоновкой, но будет накапливать базу для динамической компоновки.
Нужно поточнее списочек.Цитата:
Сообщение от Vitamin
В предыдущих вариантах этой темы высказывались конкретные предложения. Надо их все собрать, упорядочить, углубить, уширить. Опубликовать. Затем программисты поскребут в своих запасах.
А бывают "библиотеки классов"? :)Цитата:
Сообщение от elf/2
какая-такая проверка сигнатур при динамической линковке? этого даже в винде, где ресурсов много, не делают. а тем более откуда сигнатуры брать в случае ассемблера?Цитата:
Сообщение от captain cobalt
Именно поэтому нужен контроль интерфейса не просто по имени, а по сигнатуре.Цитата:
Сообщение от maximk
На заскоки старших братьев конкретно от Microsoft можно не обращать внимания. :)
Это уже следующий вопрос.Цитата:
Сообщение от maximk
Нужны не просто библиотеки. Нужен framework. Эдакий каркас с ячейками, в которые можно вставлять свой код.
Программирование становится намного комфортнее.
Но здесь сейчас опять у кого-нибудь случится истерика.
Поправочка.Цитата:
Сообщение от elf/2
Не делали.
Теперь, когда DLL hell доканал, придумали новые чудеса техники.
Прописывать вручную.Цитата:
Сообщение от elf/2
я слышал что dll hell был связан с несовместимостью версий библиотек... но тем неменее чудеса техники в студию. как теперь с этим борються? уж не предагается ли reflection на спекке делать?Цитата:
Сообщение от captain cobalt
фтопку! слишком много ошибок будет и главное не понятно как их потом проверять. тоже руками :) ?Цитата:
Сообщение от captain cobalt
А почему предпочитает? Потому что "кого хочу- не знаю, кого знаю- не хочу". Я вот тоже свой UI писал по мотивам SupremeGUI от DT. Была б она открыта (в то время)- использовал бы ее и все... А будет выбор- будет использование.Цитата:
Сообщение от maximk
У меня по этому поводу одна идея- проводить вырезание только нужных функций. Но это требует ресурсов и может быть применено только при окончательной сборке бинарника (не runtime).Цитата:
Сообщение от maximk
А про CP/M (точнее, реализацию) поподробнее можно?
Это уже интимные проблемы компилятора. Будет кешировать- будут в памяти, не будет кешировать- будет елозить по диску.Цитата:
Сообщение от captain cobalt
Хранить внутри файла библиотеки. Если жалко места на строку видаЦитата:
Сообщение от elf/2
memcpy[сигнатура в бешеном формате], то можно делать хеширование в 3-4 байта и не мучаться. Само собой, линковщик должен это учитывать
Например в дотнете сборки контролируются по номеру версии.Цитата:
Сообщение от elf/2
На спеке предлагается контроль сигнатур по хэшам.
Есть предложение совместить это с системой автодокументирования исходника.Цитата:
Сообщение от elf/2
Из исходника компилируется отдельно объектный код, отдельно - документация.
Проверочные хэши генерируются из ключевых кусков документации.
Идея в том, что по неправильной документации невозможно написать правильный клиентский код. :)
Далее работает правило: "если документация, по которой программист писал клиентский код не совпадает с текущей документацией - компоновка не происходит". :)
Ну так лучше, если они будут сидеть скомпонованные друг с другом. Сидеть и не двигаться с места. Новый код будет помещаться в свободную память и прикомпоновываться к ним.Цитата:
Сообщение от Vitamin
Я не говорил, что либман - есть как в амиге. Это полностью творение рук Шаоса. Как он его реализовал - не вдавался. А вот в начале (первый толчек к созданию) я поучаствовал. Но это не говорит о том, что это копия с амиги.Цитата:
Сообщение от Vitamin
По поводу переходов - на амиге никаких вычислений, догадайся почему 8)
Цитата:
Сообщение от captain cobalt
Цитата:
Сообщение от captain cobalt
даже комментировать не хочется :( если все это про динамические библиотеки.Цитата:
Сообщение от Vitamin
1. генерация/проверка сигнатур должна делаться автоматически. на асме типов нет, и параметры передаются как бог на душу положит. значит автомат идет лесом
2. кто видел нормально комментированый код на спеке?
3. проверка будет жрать кучу времени... а вы только что плющили амижников по поводу "тормозов аналогичных ООП"
Вот более подробное изложение: ;)Цитата:
Сообщение от elf/2
Цитата:
Сообщение от сетевой фолклор
Да.Цитата:
Сообщение от elf/2
Воспользоваться чужим кодом без документации невозможно.Цитата:
Сообщение от elf/2
Код для повторного использования должен быть документированым.
Передача параметров описывается в документации. Из этих кусков документации генерируются проверочные хэши.Цитата:
Сообщение от elf/2
Для каждого экспортированного-импортированного символа сравнить два числа.Цитата:
Сообщение от elf/2
Никаких накладных расходов во время выполнения.
Значит автомат не идёт лесом.Цитата:
Сообщение от elf/2
Плохо.Цитата:
Сообщение от elf/2
Есть два основных выхода:
1. Подсмотреть ООП на ПЦ (в TASM и т. п.).
2. Использовать typed assembly language, "типизированный ассемблер", сокращённо TAL. Идея в принципе прикручиваема к Z80. Но это - как раз сильно отдалённое будущее, о котором будем говорить гораздо позже. Ссылки здесь.
И что с того? От осознавания мною того факта, что на амиге не делаются вычисления, на спектруме они не исчезнут. Так что смотреть на все возможные варианты создания релоцируемых бинарников надо через призму возможностей спектрума.Цитата:
Сообщение от acidrain
ЗЫ. Доки получил?
Откуда компилятор должен брать исходные данны для генерации сигнатуры? Из астрала чтоли? :) Ручками прописать. А типы на асме есть, стыдно говорить что нету! %) И передача параметров (распределение регистров) прекрасно можно описать в сигнатуре. В связи с этим отпадает необходимость тянуть мегабайт документации с описанием в какие регистры надо засовывать параметры и постоянно в нее шариться.Цитата:
Сообщение от elf/2
ЗЫ. Чета идея генерации хеша по документации не вставляет- а ну запятую переставишь в описании и все, новая версия?
Проверка по хешу довольно быстра. А по поводу тормозов- если б система амиги предоставляла такой же широкий круг возможностей, то и разговора не было бы. Просто использовали и все.Цитата:
Сообщение от elf/2
Кстати я тут подумал по поводу применения полиморфизма для уменьшения размера бинарников.
Предположим, мы имеем абстрактную библиотеку GUI с кучей разных типов виджетов. Как это обычно делается? Некоторая структурка в памяти, у которой есть числовой идентификатор. А гдето в функции вывода (создания, удаления и т.д.) висит здоровое такое ветвление с кучей проверок и кучей переходов на разные функции. Что мы имеем в итоге? Что придется тянуть всю библиотеку, даже если мы используем всего один-два вида виджета. Если библиотека распространяется в виде исходников, можно применить ключи для включения/отключения некоторых возможностей (я так у себя делал). В бинарнике такое, ясное дело, не получится.
Зато если мы имеем полиморфизм, мы полностью отделяем реализацию от типа и имеем возможность неограниченного расширения путем наследования. При этом из бинарника можно будет вырезать ненужный (сиречь неиспользуемый) код. Правда проверка на используемость получается очень и очень ресурсоемкая- все портят таблицы виртуальных функций, которые по идее уже прошиты в бинарнике, но явно нигде не светятся...
Не по всей документации, а только по "ключевым кускам".Цитата:
Сообщение от Vitamin
Сигнатура - это всё равно неотъемлемая часть документации.
Нужно лишь её определённым образом отмечать, чтобы хэш считался только от неё.
Можно каждый виджет поместить в свой модуль.Цитата:
Сообщение от Vitamin
Тогда в импорте можно прописать только те модули, которые используются. :)
проверка сигнатур нормально работает только на этапе компиляции.Цитата:
Сообщение от Vitamin
в динамике у нас есть только два имени и все. в этом случае я не вижу чем имя функции memcpy хуже memcpy_VI#43543 (написанной руками) с точки зрения безопасности и отсутствия dll hell. и главное никто проверить уже не сможет что мы ее зовем правильно просто сравнивая имена.
а нормальная проверка сигнатуры т.е. парсинг и сравнение пока не понятно с чем точно кучу времени съест.
Зачем сюда вообще прилеплять документацию? Да ни в жизни библиотеки не различались по версии описания.Цитата:
Сообщение от captain cobalt
Именно так, при этом главному менеджеру оболочки будет абсолютно монопенисуально что рисовать и как опрашивать.Цитата:
Сообщение от captain cobalt
Чего???? Как раз только на этапе линковки. Чтобы знать что и с чем склеивать.Цитата:
Сообщение от elf/2
С точки зрения линкера, все эти имена равнозначны. Но для пущей унификации весьма и весьма желательно закодировать в сигнатуре входные параметры и возвращаемый тип. Убиваем сразу несколько зайцев- можем свободно иметь перегружаемые функции, отпадает необходимость постоянно смотреть в документацию дабы вспомнить в каких регистрах параметры передаются и получаем зачин на использование ЯВУ (а компиляторы именно так кодируют названия функций)Цитата:
Сообщение от elf/2
memcpy - это имя. VI#43543 - это то самое проверочное магическое число. Оно остаётся "за кулисами". В клиентском коде используется только memcpy. VI#43543 просто копируется в клиентский модуль с объектным кодом во время компиляции. Во время динамической компоновки они просто проверяются на равенство.Цитата:
Сообщение от elf/2
Предполагается, что автор memcpy изменив интерфейс (или внеся иную несовместимость) изменит сигнатуру. Несовместимые модули не будут компоноваться. Если автор забудет изменить сигнатуру, то вспомнит когда у него что-нибудь сломается. Если у него ничего не сломается, ему сообщит кто-нибудь, у кого сломается. Если автор забил на спек, проблема может быть опубликована.
Смысл в том, чтобы несовместимость обнаруживалась легче.
Вместо того чтобы "непонятная чертовщина" накапливалась до тех пор пока не получила звание "глюкало мастдайное". :)
Сигнатура - это часть документации.Цитата:
Сообщение от Vitamin
Документация всё равно понадобится.
Поэтому - чтобы не плодить сущностей.
На самом деле в языках высокого уровня она действительно работает во время компиляции. Проверяется, что передаётся правильное количество аргументов правильных типов.Цитата:
Чего???? Как раз только на этапе линковки. Чтобы знать что и с чем склеивать.
А в ассемблере. Если мы забыли загрузить аргумент в регистр, и в регистре мусор от предыдущего использования - компилятор ничего не скажет. :(
Неа. Переводим документацию на другой язык получаем другую библиотеку? Типа был Паскаль, получили 1С? :)))Цитата:
Сообщение от captain cobalt
ППКСЦитата:
Сообщение от captain cobalt
Сущности и не будут плодиться.Цитата:
Сообщение от captain cobalt
Насколько я знаю, для создания имен используются описания интерфейсов (для С это заголовочные файлы). А вот сверка уже потом на этапе линковки.Цитата:
Сообщение от captain cobalt
А это уже везде. Вне зависимости от платформы, наличия или отсутствия ОС.Цитата:
Сообщение от captain cobalt
Я тут наброски делал по поводу организации сигнатуры. Часть подсмотрел, часть придумал сам. Вот что получилось.
Символьное имя точки.
Символьное имя может содержать в себе дополнительную информа-
цию о сигнатуре, типах параметров и возвращаемом значении (в
квадратных скобках указаны необязательные параметры):
PointName[@signature[(parameters)[#out_type(params_type)]]],\0
signature определяет сигнатуру точки (флаги в символьном экви-
валенте и типы входных параметров для точки-функции в скобках):
Uname;- пользовательский тип name
[type- указатель на тип type
{type- константный указатель на тип type
число скобок определяет вложенность, итоговая константность
определяется по типу последней скобки.
V- void
C- char
I- int
L- long
F- float
c- CARRY
z- ZERO
y- CARRY&ZERO
f- function
B- byte
W- word
D- dword
E- double
Типы c,z и y применяются только для точек-функций.
Также для точки-функции возможно уточнение типа передавае-
мых и возвращаемых значений после знака #. out_type определяет,
как возвращается значение, params_type определяют способ пере-
дачи параметров. Если уточнения нет, то параметры передаются
согласно компилятору (в случае ЯВУ). Следующие обозначения для
различных способов передачи данных:
a- регистр А, 8 бит
b- регистр B, 8 бит
c- регистр C, 8 бит
d- регистр D, 8 бит
e- регистр E, 8 бит
f- регистр F, 2 бита (ZERO & CARRY)
B- регистр BC, 16 бит
H- регистр HL, 16 бит
L- регистр HLDE, 32 бита (HL- старшие биты)
D- регистр DE, 16 бит
E- регистр DEHL, 32 бита (DE- старшие биты)
X- регистр IX, 16 бит
Y- регистр IY, 16 бит
m<name>- в области памяти с именем name.
sN- по смещению в стеке в N байт от SP на момент старта про-
цедуры. Для доступа к переменным может использоваться сле-
дующий код:
PointName:
ld iy,-2
add iy,sp
...
ld a,(iy+N)
...
ld l,(iy+N)
ld h,(iy+N+1)
...
Пример кодирования сигнатуры экспортируемых точек:
int integerVariable; => integerVariable@I,\0
char* strcpy(char* dst, const char* src); => strcpy@[C([C{C),\0
или, при спецификации регистров (in=de,hl, out=de):
strcpy@[C([C{C)#D(DH),\0
void myfunc(mytype** ptr); => myfunc@V([[Umytype),\0
Ещё нужны inline константные аргументы, размещаемые в коде типаЦитата:
Сообщение от Vitamin
CALL target
DB 5
DW #7ffd
; сюда возврат
Что это?Цитата:
Сообщение от Vitamin
Рассмотрим на примереЦитата:
Сообщение от Vitamin
Две точки с запятой - это комментарий документатора.Код:;; @sig strcpy@[C([C{C)#D(DH)
;; Копирование строки
;; @arg HL - источник
;; @arg DE - приёмник
;; @ret DE - результат
strcpy LD A,(HL) ; пошла сама процедура
С собаки начинаются тэги документатора.
@sig - объявление сигнатуры, которое хэшируется и попадает в модуль с объектным кодом.
Остальное попадает в документацию. Без тэга - просто переписывается в документацию. @arg и @ret - оформляется в документации соответствующими разделами.
Ну разве не заглядение? ;)
сложна имхо реализация... смещения только последовательно и плясать от адреса возвратаЦитата:
Сообщение от captain cobalt
завершающий 0. сишный синтаксис приплел %)Цитата:
Сообщение от captain cobalt
У мя не так, у мя документация отдельно, директивы компилятора отдельно. Типа:Цитата:
Сообщение от captain cobalt
__PUBLIC "strcpy@[C([C{C)#D(DH)",FUNCTION
ld a,(hl)
...
Без этой директивы данная строчка не будет интерпретироваться как начало процедуры. Потому как у тебя без специального компилятора, умеющего разбирать теги в комментах символические имена генериться не будут
пересилил я себя, в который раз причём
Я витамина сразу понял а вот основная масса участников видимо не прониклась духом идеи - как говорят софисты "прежде чем отергать идею, надо проникнуть её духом"
Витамин спросил - какова вообще идея?
Я считаю что идея отличная, и ставлю за идею 5 баллов.
Далее, что плохого есть в идее.
Как уже отмечено инерция мышления и как итог - инерция в методиких создания программных продуктах на спекке. Но речь не об этом.
Мне кажется основная масса непоняток выходит из того, что витамин недостаточно внятно объяснил что это даст. А я попытаюсь это сделать.
Вот такая общая мысль.
Каждый из нас сталкивался при написании своих программ с тем, что надо рисовать 1 единственный символ в заданном знакоместе из заданного шрифта (расположенного в памяти). Стандартное RST 8 кажется по-моему только на заре программирования использовали - каждый сейчас пользует для этого свой код. Даже в случае, если надо рисовать символ 8x8 точек (что справедливо далеко не всегда). Вот первый претендент - процедура прорисовки символов. (здесь не торопитесь писать "опровержение", потерпите и дочитатайте тред до конца). Вызов - в программе - на внешнюю точку Call Scr.PrintChar8x8 (первая часть имени функции обозначает его модуль - модуль Scr)
Каждый из нас сталкивался с тем, что отсутствует эффективная процедура работы с диском (опять же стандартная #3D13 слишком медленнная, и даже имеющиеся в ней возможности порой значительно ограничены). Тут уж я исключаю такого рода проблемы как поддержка (полная) жёсткого диска, работа с расширенной файловой системой TRDOS Directory System и т.д. Поэтому второй претендет - бинарник для работы с носителями, в том числе с файлами. Вызов Disc.FileRead, Disc.SectorRead, Disc.SectorWrite. Кстати не факт, что даже те процедуры что сейчас есть для скачивания работают хорошо - я вот специально для себя писал очень хитрый дискожуйный процедур, который работает не посекторно а потреково, что уменьшает время решения разрешаемых ошибок чтения и уменьшает "головобуйство" дисководов, экономя их ресурс в том числе, но опять же не про это речь. Модуль - Disc.
Модуль опроса клавиатуры.
Не секрет, что клавиатурный менеджер висящий на прерываниях спекка опять же оставляет желать лучшего - нет буферизации нажатых символов, нет возможности (через него) определить нажатие функциональных клавиш - таких как SymShift, CapsShift; русскоязычная поддержка это вообще из области фантастики. KB.ReadKey - читает клавишу нажатую пользователем. KB.Clear - очищает буфер. Модуль соответственно - KB.
Модуль рисования всеразличных рамок - Window. Window.Show - прорисовывает окошко. Тут даже может быть целая система, учитывающая взаимозакрывания окошек (т.е. когда окошко одно частично закрыто другим, а потом это заднее окошко всплывает).
Модуль арифметических операций Arithm - работает с быстрой целочисленной арифметикой (скорость калькулятора ПЗУ SOS оставляет желать лучшего, хотя функционал там конечно богатый). Arithm.16mul16 - перемножает два 16битных числа. Arithm.16div16 - делает одно 16разрядное на другое.
Модуль работы с памятью - RAM. RAM.ChangePh - смена страницы памяти на заданную физическую. RAM.ChangeLog - смена страницы памяти на заданную логическую.
И вот, я хочу написать бут, хочу написать текстовый редактор, хочу написать вьюер, хочу написать игрушку. Что из этих процедур я буду использовать? Правильно - все из них. И тем не менее, в существующей среде каждая из программ использует свой воз и тележку - где хранится это всё добро, и мало того - по причине закрытости исходов, нежелания автора заниматься программой и т.д. и т.п. в программах есть глюки, которые (90%) являются следствием криво написанных перечисленных процедур. Т.е. битком забитый диск программами спекковский диск де факто повторяет себя почти на 90%. Кроме того, часто указанные процедуры цепляются к тексту в виде некоего дополнения к каждой из запускаемых программ - в итоге и без того ограниченное количество допустимых файл-ячеек в ТРДОС используется малоэффективно.
И теперь смотрим как это может быть - на диске лежит 1 pak файл, лежит 1 boot.B и кусочек кода к нему и лежат куча стартеров - файлов скажем с расширением R (взято произвольно, кстати они тоже могут быть в виде одного файла, и вообще здесь файловая структура не так критична). Эти стартеры могут быть и бейсик программами и просто кодом - это не так важно. Важно, что boot.b загрузит при старте линковщик (или компилятор если угодно), который будет уже работать с лежащими в pak файле указанными модулями.
Хочется подчеркнуть такой немаловажный с моей точки зрения момент - модули фактически являются законченным машинным под Z80 кодом с той лишь разницей, что он сопровождается заголовком релокации для того, чтобы можно было склеить эти модули с головной программой. Впрочем, лучше почитать документацию к модулям и станет понятно что обвинения в писюканстве и амижстве здесь бессмысленные.
И вот, запускаю я свой излюбленный вьюер - и что же? фактически, загрузится МОЯ логика реализованная в коде Z80 - мой код (назову это индивидуальный код) - т.е. только то, что в общем то и надо было написать для того чтобы куча библиотек превратилась в вьюер [основная масса существующего программного зоопарка несовершенна по причинами того, что кодер реализовав свою логику, которая на самом деле является изюминкой программы должен ещё и написать процедуры для отработки указанных действий - работы с дисками, клавиатурой, арифсетика, память и т.д.] - код будет просто дёргать нужные функции и я не буду задумываться о реализации универсального драйвера памяти (кроме случая когда он будет для меня слишком медленный, но это около 1% случаев всего кодописания), я не буду задумываться куда мне обратиться за опросом клавиатуры, я не буду задумываться даже на каком устройстве я сейчас работаю - потому что драйвер уже это сделает, потому что он включен в программу - ну и т.д.
Теперь, нажал я резет. Надоел мне вьюер, я захотел текст понабирать - и всё то же самое - загрузился только МОЙ индивидуальный код и все остальные модули подхватились сами.
Кстати тут очень интересный вариант, что модули будут лежать даже не на самом диске, а скажем на ЖД, или например во втором дисководе будет лежать диск с модулями - т.е. даже отпадёт необходимость на конечный диск писать библиотеки.
Общая мысль витамина такая - за каждой из программ тянется огромный шлейф повторно написанных процедур (вот уж действительно пора покончить с изобретением велика), которые можно и нужно использовать в стандартном виде и таким образом подтягивать и увеличивать общую эффективность программо-производства.
Напоследок хочу сравнить два подхода - которые как мне кажется в некотором смысле конкурирующие - 1) когда имеются ИСХОДНИКИ всех используемых процедур и в процессе компиляции всё собирается в один конечный файл 2) когда имеется модульная структура и фактически компилируется только индивидуальный код.
1) возможность расширения 100% за счёт стороннего кода; возможность подмены исходных возможно глючных библиотек - только при перекомпиляции всего кода; количество необходимых файлов (в килобайтах и в штуках) - большое
2) возможность расширения - отсутствует, это готовый код - только при перекомпиляции; возможность подмены библиотек - 100% за счёт модульной организации; количество необходимых файлоы (в штуках и килобайтах) - невелико.
Имеется ввиду, нужен синтаксис для сигнатуры.Цитата:
Сообщение от Vitamin
Технология использования таких аргументов хорошо отработана. Например:
Даже более привлекательно, чем ковыряться в стеке через индексные регистры.Код:EX (SP),HL
LD A,(HL)
INC HL
LD C,(HL)
INC HL
LD B,(HL)
INC HL
EX (SP),HL
С другой стороны, можно вспомнить о необходимости постепенной миграции со статической компононовки на динамическую.Цитата:
Сообщение от Vitamin
Код с сигнатурой в комментарии можно компилировать прямо сейчас, в любом ассемблере (после токенизации). То есть сию секунду можно нарабатывать код. Параллельно можно разрабатывать спец компилятор и документатор.
Код на макросах ALASM зависит от ALASM, который не всем нравится. И лишь макросами всё равно не выкрутиться. Например, хотелось бы выражения от импортированных символов, которые сохранялись бы в компилированных модулях и вычислялись во время компоновки (опять вспоминаем обратную польскую запись в iS-DOS).
Не очень удачное название функции.Цитата:
Сообщение от GriV
Список модулей хороший.
Ну вот опять.Цитата:
Сообщение от GriV
Не надо нажимать RESET.
Надо выйти из вьюера. Динамический компоновщик и модули останутся в памяти.
Загрузить текстовый редактор. Он будет использовать модули уже находящиеся в памяти.
Есть что-нибудь против такого подхода?
Возможность расширения - за счёт добавления модулей.Цитата:
Сообщение от GriV
Уже использованный один раз модули надо будет подгружать ещё раз или держать отдельную партию где то в памяти. Фишка в том, что уже "вставленные" в программу модули не получится отделить от программы - это такое свойство модульной структуры.Цитата:
Сообщение от captain cobalt
Всё-таки я тебе рекомендую посмотреть и разобраться досконально со структурой модулей. С моей точки зрения такой подход совместим только с отдельно фунциклирующей ОСью, а никак не самостоятельные приложения.
Впрочем здесь нет ограничений на решения, ежели boot.b будет настолько "умным" то возможен и такой вариант - он грузит контейнер модуля в вырхнюю память, а в нижнюю копирует его присоединяет к программе и поехали...
Ты здесь чего-то недопонимаешь, опять же наверное из-за модулей. Ты можешь расширять программу только когда ты её пишешь - модули же уже написанные и откомпилированные программы (пусть и в особом контейнере). Чтобы чего-нибудь там расширить придётся грузить ассемблер (или ЯВУ если угодно) править программу и включать в неё указание на эти модули. Технология динамической подгрузки здесь не канает, потому что уже запущенное приложение не должно нуждаться ни в одной библиотеке и работать самостоятельно.Цитата:
Сообщение от captain cobalt
Если же утверждается обратное, то ещё раз - это уже будет не бут-линковщик и целая ОСь.
2Vitamin> какие уже (в настоящее время) есть вещи так или иначе связанные с модульной организацией (полный список, включая документацию). Что нужно чтобы сие стало "скорее живым, нежели мёртвым"?
Уважаемый captain cobalt, скажите, вы вживую видели 'подход библиотек Амиги'? Я что-то сомневаюсь... Вы вон давеча ажно драйвер памяти аласма записали в ООП или куда там. Признайтесь, вы даже его в глаза не видели?!Цитата:
Сообщение от captain cobalt
Вы в жизни не видели процессоры архитектуры 68к, вам мало 15 32-битных регистров? Это вам не х86, где каждый регистр на вес золота.Цитата:
Сообщение от captain cobalt
Кроме того, извольте продемонстрировать тормоза вызовов библиотек амиги, не будьте голословным!
Например так:
Код:jsr _LVOFunctionName(a6) ; тут безусловно тормоза, целых 2 слова выбираются из памяти, по сравнению с
jsr absolute_address ; абсолютным вызовом, где один только адрес занимает 2 слова
Цитата:
то у Амиги "просто библиотеки". :)