не более расточительно, чем хранить таблицы переходов для каждой подфункции. зато геморроя меньше.Цитата:
Сообщение от axor
Вид для печати
не более расточительно, чем хранить таблицы переходов для каждой подфункции. зато геморроя меньше.Цитата:
Сообщение от axor
Длина таблиц подфункций ограничена количеством этих самых подфункций. Количество же функций должно быть максимально возможным. Это по моему вразумению. Но, как водится, у каждого оно свое.Цитата:
Сообщение от Vitamin
А тут никто не подумал, что будет если пытливый мозг вроде моего попытается вызвать подфункцию с номером, превышающим число подфункций у данной функции? В лучшем случае будет вызов совсем другой проги, а в худшем - ступор компа. Либо защиту от такого мараZьма ставить надо, либо избавляться от подфункций.
RST использовались как функции в Спринтере 2000 в его ОСИ Estex. Можно сказать достаточно удобно с точки зрения программирования. Хотя никто не мешает сделать керналь как в CP/M (таблицу вызовов).
Самой первой функцией, которую должна вызвать программа - это проверка номера версии ядра. Если номер версии больше, чем нужно (новее значит, а значит и все старые функции доступны), то работаем дальше, иначе, закрываем программу.Цитата:
Сообщение от SAM style
Цитата:
Сообщение от SAM style
Без этих ex (sp), hl получается существенно быстрей.
И на "несовременных пэцэтах" тоже можно. Суть не в том.Цитата:
Сообщение от Sinus
Суть в том, что номера int жёстко закреплены за функциями.
Ибо без какого-либо минимального набора вообще никак.
Да. Но это соглашение должно быть. Вот именно в этом суть.Цитата:
чтобы код программы мог быть запущен, необязательно передавать параметры через стек, патчить прогу или использовать конструкции вида RST XX: DB YY
надо всего лишь прийти к какому- либо соглашению о передаче параметров и вызовах функций. допустим
Это фактически мой вариант. Просто таблица переходов размещается в ПЗУ и патчить её не надо, потому как самоЦитата:
с адреса #0000 находится 256 jp XXXX. это системные вызовы. параметры передаются в регистрах. если нужно передать адрес, то он всегда в HL, если нужно передать один байт, то он всегда в A.
ПЗУ уж знает где его функции находятся.
Что касается аргументов я предпочитаю следовать соглашениям
принятым для компилятора HiTech-C. Они достаточно удобны.
Аргументы передаются в DE, BC и далее в стеке. Результат
возвращается в HL. Иногда я отступаю от таких соглашений,
когда передача через HL или A более эффективна. Но такие
функции обычно "внутренние" для программы, наружу не
экспортируются, поэтому в их отношении допустимо всё что
угодно.
Регистр HL и A имеют специальное значение. При программировании
в OO-стиле в HL содержится указатель на структуру-объект,
первым элементом которой является адрес массива "JP xxx" указателей виртуальных функций. При вызове виртуальной функции
регистр A используется под её номер (до 85 функций). Схема
примерно такая:
Множественное наследование не предусмотрено, ибо сложноКод:
; В коде программы:
...
ld hl, object_or_inherited_object
call virtual_function
...
call non_virtual_function
...
; В коде включаемого "*.h"-файла
virtual_function:
ld a, function_number
jp call_virtual
...
; таблица функций -- патчится после загрузки:
; номера функций заменяются их адресами извлечёнными
; из таблицы функций библиотеки (располагается в файле библиотеки)
non_virtual_function:
jp function_number
non_virtual_function2:
jp function_number2
...
; В коде файла поддержки виртуальных функций:
call_virtual:
; здесь A складывается с (HL) и извлекается адрес
; из таблицы виртуальных функций
; присутствующей в файле библиотеки
....
ex (sp), hl
ret ; ~120 тактов
;---------------------------------------------------------------------
; В коде файла библиотеки
; ВАЖНО: компилируется НЕЗАВИСИМО от файла основной программы
; и динамически подгружается "на лету"
virtual_function:
.... ; обычный код
ret
non_virtual_function:
.... ; обычный код
ret
получается.
Да. Был бы на это ЕДИНЫЙ СТАНДАРТ...Цитата:
далее всё зашибенно работает.
это если объектами рулить.Цитата:
Сообщение от fk0
как показывает практика, ООП эффективно только на достаточно больших задачах.
в случае спектрума зачастую обычный процедурный подход оказывается эффективнее.
оно нужно так же как и goto (т.е. ненужно почти никогда)Цитата:
Множественное наследование не предусмотрено, ибо сложно
получается.
о! да...Цитата:
Да. Был бы на это ЕДИНЫЙ СТАНДАРТ...
но его нет ^_~
а почему бы не использовать для этих целей индексный регистр? имхо это более рационально (все-таки структура). а вторую регистровую пару использовать для хранения адреса переменных на стеке. получается довольно неплохоЦитата:
Сообщение от fk0
Практика показывает, во-первых, что и из мухи можно раздуть большую задачу. Во-вторых эффективного и неэффективногоЦитата:
Сообщение от Sinus
ООП и чего-нибудь ещё попросту не бывает. Вполне конкретную
задачу (программу) можно рассматривать как с точки зрения ООП,
так и как систему конечных автоматов, как и чёрт знает что ещё --
она от этого не меняется. Просто не нужно упираться во что-то
одно.
Отсутствие goto -- это вынос блока в отдельную функцию.Цитата:
оно нужно так же как и goto (т.е. ненужно почти никогда)
Отдельная функция -- это отдельное несвязанное пространство
имён и связывание переменных через аргументы по ссылке.
Или, как альтернатива, масса логических условий прекращения цикла.
В целом получается достаточно запутанно для понимания и неэффективно с точки зрения кодирования.
А если идти и дальше
этим путём, то любые операторы ветвления и циклов тоже
не нужны. Ибо они реально, без почти, не нужны. Программа
может быть элементарно преобразована в эквиэвалентную,
использующую исключительно функции и оператор '?' (в языке C).
Глупость про ненужность goto -- это типичный "слышал звон,
но совершенно не в курсе дела о чём вообще речь". Если он такой
ненужный, чего ж он мало того, что в последних версиях стандартов
остался, так ещё и обрастает разными расширениями? То-есть
да, он таки не нужен, ровно в той степени, как ненужны while и for.