Оберон и ассемблер
Сопряжение с ассемблером
Передача параметров
Передача параметров в регистрах в SDCC
не реализована,хотя Филипп Краузе и обещал
над этим подумать.Параметры функциям пере─
даются в стеке,верхним хранится адрес воз─
врата.Есть несколько способов получить па─
раметры, и вам необходимо выбрать наиболее
приемлемый. Если параметр(ы) занимает(ют)
1 или 2 байта,то неплохим будет такой код:
POP HL; Адрес возврата
POP BC; Однобайтовый параметр ─ в C,
PUSH BC; а если двухбайтовый, то в BC
PUSH HL; Если в процедуре HL не
; портится, то можно заменить
; PUSH HL:RET на JP (HL)
Или же так (такты и байты считайте сами):
LD HL,#2
ADD HL,SP
LD C,(HL); 1-й байт параметра(ов)
INC HL
LD B,(HL); 2-й байт параметра(ов)
Если глубоко в теле подпрограммы требуется
получение параметров в произвольном поряд─
ке, то, возможно, более оптимальным будет
адресовать параметры черезIX:
PUSH IX
LD IX,#0
ADD IX,SP
LD C,4(IX); 1-й байт параметра(ов)
LD B,5(IX); 2-й байт параметра(ов)
...
POP IX
Функция не должна извлекать свои параметры
из стека совсем, ─ в модели вызова по умо─
лчанию компилятор сам извлекает параметры
после возвращения из функции (что в ряде
случаев помогает ему оптимизировать код).
Также функция не должна разрушать содержи─
мое регистраIX, через который SDCC рабо─
тает с локальными переменными.
Результат функций в зависимости от раз─
мера возвращается в регистреL, в паре HL
или вDE:HL.
Эффективный вид Z80-кода,
подходящий для портирования
Коснёмся такого интересного вопроса, как
портирование Спектрум-игр на другие плат─
формы. Не секрет, что код на ассемблере не
слишком нагляден, но зато слишком объёмен.
И для прояснения его логики часто приходи─
тся очень подробно разбирать огромные кус─
ки кода, пытаясь понять и описать, что они
делают. Результаты такой кропотливой рабо─
ты не грех задокументировать, переписывая
на более высокоуровневый язык, и здесь нам
может помочь XDev, который предоставляет
язык достаточно простой,чтобы быть развёр─
нутым на других платформах,но и достаточно
современный концептуально, ибо,несмотря на
свой почти 30-летний возраст,прекрасно ло─
жится практически на все современные аппа─
ратные и программные платформы,что я демо─
нстрировал примерами мидлетов наОбероне
(http://zx.oberon2.ru/forum/
viewtopic.php?f=27&t=38 )
и даже некоторыми подвижками в разработке
для Android
(http://zx.oberon2.ru/forum/
viewtopic.php?f=87&t=244 ).
А вот, например,Си, насколько мне из─
вестно, нельзя транслировать в байт-код
Dalvik и в Java .class'ы, ибо Си имеет
слишком много опасных возможностей, от ко─
торых в Java-машинах постарались избавить─
ся на уровне байт-кода. То же самое можно
сказать о браузерных приложениях.Оберон
же прекрасно ложится даже на микроконтрол─
леры
(http://www.youtube.com/
watch?v=zlnjбFCY1tY ),
не говоря уж оJVM и .NET
(http://gpcp.codeplex.com ).
К сожалению,формат журнальной статьи не
позволяет развёрнуто описать процессы миг─
рации Z80-кода на другие платформы,но если
вам интересно, как могут выглядеть интер─
фейсы библиотек и прикладной код, трансли─
руемый в различные (очень различные!) тар─
геты, то смотрите среду XDev (и её подсис─
темы для разработки под разные платформы)
и среду Monkey X(http://monkey-x.ru), ко─
торая также предлагает трансляцию с едино─
го языка под различные таргеты, что при
всех недостатках реализации (ей далеко до
универсальности, но всё нужно развивать)
экономит время и ресурсы, которые в проти─
вном случае тратились бы на изучение деся─
тков (быстроменяющихся) языков, платформ и
их API.
Ещё хотелось бы отметить,что я не видел
ни одного удовлетворительного решения для
одномоментной разработки для Спека и дру─
гих платформ. Вы можете возразить, что ни─
кого не интересует скрещивание Спека с ПЦ.
Я же могу возразить в ответ ─ а почему
одинаковая программа или игра должна быть
написана по-разному для разных платформ? И
особенно на разных языках, которых сейчас
как собак нерезаных.Устаю удивляться,когда
просто читаю новые названия языков. Не
кроется ли здесь проблема, которой вы не
заметили?
Так почему же я не считаюСи таким хо─
рошим средством для одномоментной разрабо─
тки. Во-первых, см. выше о том, какСи ло─
жится на современные платформы, а, вернее,
уже не ложится. Во-вторых, посмотрите не─
предвзятым взглядом на исходники любой иг─
рушки для Спектрума, написанной наСи[ну,
не считая игр на движке Churrera -Ред.].
Вы не обращали ранее внимания на обилие
вставок на асме? Так вот,я вас уверяю: это
приговор. Хотя и приятно, что не целиком
всё на асме.Вобщем,не видел ни одного сре─
дства разработки, при помощи которого уда─
лось бы хотя бы частично автоматизировать
процесс вытаскивания игры из рамок спект─
румных ограничений. Нужно всё переписывать
заново. XDev тоже не является таким средс─
твом,ноОберон как язык при всей жёсткости
его каркаса и обилии ограничений ─ в об─
щем-то хорошая основа для мультитаргетной
разработки, как мне кажется. Но предстоит
изучение его возможностей в этом плане и,
разумеется,их совершенствование. Важно по─
нимать, что я не предлагаю панацею, просто
обозначаю проблему и призываю искать пути
её решения, если вам это интересно.
Мы мигрируем от Z80-асма кСи, но, не
найдя в нём достаточной опоры для приклад─
ного высокоуровневого программирования ─
безопасного, наглядного средства для прог─
рамм со сложной структурой и мета-програм─
мирования (скриптования)
(http://forum.oberoncore.ru/
viewtopic.php?f=6&t=5267 ),
оставаясь в рамках компилируемого кода, мы
движемся дальше,к Оберону, но оставляем за
собой возможность юзать для низкого уровня
и асм, иСи, и Java, если понадобится (по─
следнее не для ZX,конечно,а для Java-based
платформ). Вот поэтому я вижу языкСи в
применении к другим платформам в роли асма
Z80 для Спека. Хорошо для низкого уровня,
но начинает нервировать, когда идёт работа
со сложной прикладной логикой.
С учётом того, что к коду на Z80 хорошо
бы приложить удобный и однозначно соответ─
ствующий логике асмовского код на языке
высокого уровня, а главное ─ компилируемый
и исполняемый (а в идеале ─ ещё и кросс─
платформенный!), оставляя за бортом упоми─
нание о множестве проблем совместимости и
различий по библиотекам, интерфейсам и ещё
много чего, просто покажу, как может выг─
лядеть код,реализующий игру для Спектрума/
Z80 и других платформ одномоментно, вовсе
не утверждая, кстати, что XDev ─ идеальная
среда для этих применений (в этот момент
асмеры кричат "маздай" и бьются в парокси─
змах ЯВУ-ненавистничества в применении к
Спектруму).
Итак,вот процедура опроса клавиатуры из
игры "Дурак" от CopperFeet, портированная
наОберон с Laser Basic'а, а потом допол─
ненная альтернативной реализацией на ассе─
мблере:
MODULE Durak;
IMPORT M := Asm, B := Basic, Cfg;
TYPE KeyCode = CHAR; VAR time: INTEGER;
(* Scan keys & return a control code: *)
PROCEDURE GetKey (): KeyCode;
BEGIN
IF Cfg.Oberon THEN
(* ~ 2 min 50 sec to play music: *)
DEC(time, 9); B.PAUSE(9);
(* <Y>, <U>, <I>, <O>, <P>: *)
IF BITS(B.PORTIN(ODFFEH))*BITS(1FH)
# BITS(1FH) THEN RETURN 2X END;
(* <Q>, <W>, <E>, <R>, <T>: *)
IF BITS(B.PORTIN(OFBFEH))*BITS(1FH)
# BITS(1FH) THEN RETURN 1X END;
(* <A>, <S>, <D>, <F>, <G>: *)
IF BITS(B.PORTIN(OFDFEH))*BITS(1FH)
# BITS(1FH) THEN RETURN 3X END;
(* <H>, <J>, <K>, <L>, <Enter>: *)
IF BITS(B.PORTIN(OBFFEH))*BITS(1FH)
# BITS(1FH) THEN RETURN 4X END;
(* <B>, <N>, <M>, <SS>, <Space>: *)
IF BITS(B.PORTIN( 7FFEH))*BITS(1FH)
# BITS(1FH) THEN RETURN 5X END;
ELSE
(* DEC(time, 9): *)
M.Code("LD HL, (_Durak_time) ");
M.Code("LD DE, #0-9 ");
M.Code("ADD HL, DE ");
M.Code("LD (_Durak_time), HL ");
(* B.PAUSE(9): *)
M.Code("LD HL, #9 ");
M.Code("PUSH HL ");
M.Code("CALL _Basic_PAUSE_DI_stdcall");
(* <Y>, <U>, <I>, <O>, <P>: *)
M.Code("LD BC, #OxDFFE ");
M.Code("IN A, (C) ");
M.Code("CPL ");
M.Code("AND #0x1F ");
M.Code("LD L, #2 ");
M.Code("RET Z ");
(* <Q>, <W>, <E>, <R>, <T>: *)
M.Code("DEC L ");
M.Code("LD BC, #OxFBFE ");
M.Code("IN A, (C) ");
M.Code("CPL ");
M.Code("AND #0x1F ");
M.Code("RET Z ");
(* <A>, <S>, <D>, <F>, <G>: *)
M.Code("LD BC,#OxFDFE ");
M.Code("IN A, (C) ");
M.Code("CPL ");
M.Code("AND #0x1F ");
M.Code("LD L, #3 ");
M.Code("RET Z ");
(* <H>, <J>, <K>, <L>, <Enter>: *)
M.Code("INC L ");
M.Code("LD BC, #OxBFFE ");
M.Code("IN A, (C) ");
M.Code("CPL ");
M.Code("AND #0x1F ");
M.Code("RET Z ");
(* <B>, <N>, <M>, <SS>, <Space>: *)
M.Code("INC L ");
M.Code("LD BC, #0x7FFE ");
M.Code("IN A, (C) ");
M.Code("CPL ");
M.Code("AND #0x1F ");
M.Code("RET Z ");
END;
RETURN 0X
END GetKey;
END Durak.
Что любопытно, асмовский код, конечно,
компактнее,но если сжать это дело Hrum'ом,
то в результате сжатая обероновская реали─
зация по размеру меньше, чем сжатая асмов─
ская. Что позволяет сделать смелый вывод:
при достаточном количестве памяти и быст─
родействии в случае загрузки машинного ко─
да в уже сжатом виде (и при разумной ско─
рости распаковки) остаётся экономить лишь
адресное пространство,которое в таком слу─
чае и является основным ресурсом для эко─
номии и самым весомым аргументом за асм-
реализацию в случае его недостаточности,
тогда как для некоторых проблем важнее
иметь не столько экономию адресного прост─
ранства, сколько бОльшую простоту и гиб─
кость разработки (макетирование,прототипи─
рование, средства отладки и т.д.). [Впро─
чем,мы можем использовать интерпретируемый
пи-код для экономии адресного пространст─
ва, потеряв при этом в скорости -Ред.]
Возможности Оберон-языков,
отсутствующие в ZXDev
Есть ряд возможностейОберона, которые
вряд ли будут когда-либо реализованы для
разработки под процессор Z80. Это динами─
ческая модульность (загрузка-выгрузка мо─
дулей "на лету"),автоматическое управление
памятью (сборка мусора; но пользоваться
динамической памятью всё-таки можно, явно
освобождая её с помощьюPlatform.DISPOSE),
возможности ядра по мета-программированию,
обработке исключений, моментальной (по─
смертной) отладке и т.д. Как вы понимаете,
скорости и памяти (особенно адресного про─
странства) Z80 явно недостаточно, чтобы в
полной мере почувствовать прелесть разра─
ботки на Оберон-языках.
Other articles: