Сообщение от
GriV
Не такой уж и большой - она в памяти после трансляции программы по заданным адресам будет занимать 0 (ноль) байт памяти - она просто напросто не нужна после трансляции.
Та структура, которую лоббирует витамин обладет кроме того что нет проблем с вызовами и кучей других преимуществ.
У ней функциональности нет, а не проблем нет. Проблемы у неё
начинаются прямо с ассемблера. Я, например, такой код никаким
C-компилятором сгенерировать не могу, и я это знаю. Нужно будет
писать свой ассемблер для трансляции такого кода -- вот это
проблема. В ALASM можно макросами. А как быть кто пользуется
GENS? А как быть с существующим кодом? Под него писать
обёртку вокруг всё того же JP xxx.
Это может быть хорошее решение для решения какого-то узкого круга специфических задач, где жалко каждые 10 тактов. В качестве
более общего, применимого в любой области, в любом направлении,
решения оно непригодно. Хотя бы из-за технических трудностей,
в настоящее время не решённых и решать их просто некому. И некогда.
Кроме того, указанная таблица для преобразования вызовов функций из Call 0 в Call <ClrScr> обладает значительно большей скоростью и
Значительно большей -- это, если грубо, примерно, 10/1000, а
то и 10/10000 -- 0.1..1% экономии по времени. И где-то
чуть по-больше по памяти, процентов 5 может быть. Несомненно,
это ЗНАЧИТЕЛЬНО большая скорость...
помехазащищённостью - потому что в ПЗУ Call <Адрес> с последующим JP <внутри_ПЗУ> всегда будет работать, а вот если вдруг версия ПЗУ не та?
Условимся, что БАЗОВЫЙ ИНТЕРФЕЙС ПЗУ вот такой-то. ОН НЕ МЕНЯЕТСЯ. Все последующие интерфейсы наследуются от базового, следовательно сохраняют функциональность предыдущих версий.
Осталость ввести функцию VERSION в базовый интерфейс.
Кому-то может нужно большего. Изобретайте COM под спектрум.
Вопрос отслеживания типов функций их номеров,
Я не знаю как можно трактовать понятие типа функции в
машинном коде. Функция это не болеe чем лишь какой-то код.
Равно как и в ассемблере.
отслеживания изменения их от версии к версии повергнет в ужаc самого автора треда и он на самом дела на медленный RST подсядет
Видно большого знатока. А ты пробовал? А я пробовал. Никаких проблем нет. Единожды пишется "заголовочный" файл:
Код:
function_name:
jp function_number
function_name:
jp function_number
function_name:
jp function_number
...
Всё. Новые функции при необходимости добавляются только в конец. Нумерация исключительно последовательная. Авторам софта выдаётся этот самый заголовочный файл. Никакой ручной работы по отслеживанию чего-то нет вообще.
А вот если будет модуль как у витамина, то программа просто напросто не запустится - ПЗУ выдаст ошибку "неверный номер функции" и например предложит прервать работу.
Откуда в команде CALL xxx возьмётся неверных номер функции?
Оно может возникнуть только на этапе настройки программы на адреса библиотечных функций. Ну так это сообщение возникнет в любой системе, если такая возможность предусмотрена. Можно, например, указывать общее число функций. Можно в интерфейсе самую первую функцию выделить для реализации функций получения информации об интерфейсе и возможного переключения интерфейсов (по примеру COM). Последний вариант даже лучше.
Только, насколько я понимаю, Vitamin использует не номера, а имена функций.
А теперь вот такой вопрос на засыпку - кто из писателей программ не делел такую п/п
?
И после этого ктото будет говорить что это неэффективно?
Я буду говорить. Ибо прямой LDIR в коде быстрей на 27 тактов и
не использует стек вообще.
Именно таких фрагментов кода, которые вообще то уже есть в ПЗУ не надо будет вставлять в свою программу - они так же будут вызываться CALL <> но для этого надо будет сделать соответствующую настройку, а она делается только один раз!!!
Любая настройка делается один раз. Вопрос не в том. Я утверждаю,
что "библиотечные" функции имеют, примерно, среднее время исполнения в сотни, тысячи, а то и десятки тысяч тактов. И размер
как минимум в несколько десятков байт. Экономия 10 тактов и
трёх байт в таком случае представляется бессмысленной. Что-то вроде того, что "заставь дурака богу молиться". Бессмысленно вообще измерять такты на программе 90% времени ожидающей
нажатие на кнопку или что-то в этом роде. Измерение чего-то
вроде эффективности в тактах, байтах или других величинах --
бессмысленно. Это эффективность чего? Экономии байтов? А время
потраченное на создание кода? А стоимость других затраченных
средств? А наличие механизмов отладки? (как тебе sts будет метки-то показывать в пропатченном коде?) Вопрос этот комплексный и смотреть с одного конца на него -- глупо.
А сколько раз в программе такое запускается? Не один десяток, точно знаю! очистка экрана, переброс экрана, переброс других областей и т.д. и т.п. - это всё ЕСТЬ в ПЗУ, но этим мало кто пользуется потому
Потому, что используя оптимизированную процедуру, использующую стек или LDI вместо LDIR, можно сэкономить куда больше, чем 10 тактов. На несколько порядков больше. Потому,
что процедуры в ПЗУ жутко неоптимальны. Потому, что они реализуют недостаточную или излишнюю функциональность.
что появляется зависимость от версии ПЗУ - в 82м ПЗУ одни точки, в 90м - другие,
"Точки" там примерно те же самые. В качестве эксперимента поставь
ПЗУ Basic 48 от Amstrad и убедись, что 2/3 программ перестанут работать.
или иной Call или Jp) - и колбасим версию ПЗУ хоть как - хоть суём её часть с теневое ПЗУ хоть запаковываем его и при Reset раскаковываем в память - при "патче" программы она всё равно вызовет то что надо откуда надо а никак не приведёт к сбросу или какому нить ещё иррациональному поведению.
А как программа вызовет что надо, если этого чего надо может просто не оказаться в новой версии ПЗУ?
Вопрос отнюдь не в системе вызова, а в интерфейсе. Это уже совсем другой уровень абстракции.