Ребята, вы вначале ТЗ составьте (убейте), а потом уже делите способ реализации (медведя). Я тут набор функций предлагаю, никто не поддержал, зато все ринулись в кодерство. Вначале думаем, потом кодим.
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Я написал свой интерпретатор. Стековый, но на этапе оптимизации стековые команды объединяются и рождаются безстековые операции. Дать его не могу, но могу помочь советами.
Там получился такой набор команд:
opCallFunction - вызвать стандартную функцию
opCallMethod - вызвать метод класса
opCall - вызов собственный метод (подпрограмму)
opPushSelf - поместить в стек this (указатель на свой объект)
opJmp - перейти на строку
opLongJmp - перейти на строку и освободить стек
opRet - завершить выполнение
Далее обработка исключений.
Для каждой команды указан адрес, куда следует перейти, если произошло исключение. А так же, что следует удалить из стека. После освобождения стека, в стек кладется объект Exception с описанием ошибки.
И опкоды, которые используются только в блоках FINALLY..END или EXCEPT..END (catch...end):
opTryFinallyEnd - если на верхушке стека лежит не NULL, то исключение. Иначе освободить стек.
opThrow - сгенерировать исключение по объекту лежащему в стеке.
opGetExceptionText - поместить в стек текст исключения из объекта лежащего в стеке.
Далее идут команды для работы с типами данных VARIANT, OBJECT, INTEGER, FLOAT, BOOLEAN, STRING, CURRENCY ...
Например набор команд для Integer:
opPush_i - Поместить в стек непосредственное значение
opPop_i - Освободить стек от Integer (увеличить указатель стека на sizeof(Integer))
opPushVar_i - Из переменных в стек
opPopVar_i - Сохранить из стека в переменные
opPushObj_i - Из объекта в стек
opPopObj_i - Из стека в объект
opDup_i - Дублировать значение в стеке
opAdd_i,opSub_i,opMul_i,opDivInt_i,opDiv_i,opMod_i ,
opAnd_i,opOr_i,opXor_i,opCmpE_i,opCmpNE_i,opCmpL_i ,
opCmpG_i,opCmpLE_i,opCmpGE_i,opCmpNEX_i,opNeg_i,
opShl_i, opShr_i - эти команды производят операцию с парой чисел на верхушке стека так, что остается одно число.
Да, а команда условного перехода всего одна. Она в наборе команд Boolean:
opJt_b - Перейти, если TRUE.
Но оптимизатор пораждает массу команд перехода. Например, opNeg_b + opJt_b заменяет на opJf_b
В результате оптимизации может рождится команда типа:
opPushVar_i_opPush_i_opCmpE_opJf_i(A, B, C)
которая вообще не работает со стеком. Она выполняет действие
if(variables[A] == B) ip += C;
Или вот пример оптимизации получения элемента массива:
opPush_i 0
opPushObj_o номер
opPushVar_i номер
opCallMethod arrayOfInteger::getItem
opPop_i
opPop_o
Заменяется на единственный опкод:
opArrayOfIntegerGet_o_v(A,B)
Который выполняет действие:
ArrayOfInteger* a = objectVariables+A; if(B>=a->count) throw_bound(); *st++ = a->items[B];
Эти все оптимизации ускоряют работу, но размер исходника интерпретатора занимает несколько сотен килобайт.
Последний раз редактировалось vinxru; 12.01.2012 в 17:49.
Griv, это кто же это кинулся в кодерство? Я написал "от фонаря" байт код, типа с пояснениями, в стековой реализации, которая на мой, может быть не хужее "хипной". А ТЗ мы уже похерили, только вот медведь не делится на ноль, хоть тресни меня битой в лоб
Уже несколько раз перечитал первый пост AlCo, возникло подозрение, что первоначальная мысль была отнюдь не за байт-код, а именно некоторое подобие муляции кода Z80 с возможностью дополнения новыми командами а-ля префикс типа неиспользуемого rst x.
AlCo, выходи уже из раздумий, а то я пошел за варенным кофе!
А что бы и не JP (HL)? Да и это всё равно мелочи реализации.
Oleg N. Cher, Идея неплохая
рекомендую также посмотреть игру IronLord от UbiSoft
Разумеется изнутри
есть вероятность что либо Форт либо какой то свой язык
С уважением,
Jerri / Red Triangle.
Вот подумалось тут ещё, а адреса-то должны быть виртуальными...Код:DI LD SP, ExecThread RET
Последний раз редактировалось NovaStorm; 13.08.2012 в 12:02.
а сейчас это называется Return Oriented Programming и широко используется во взломах программ.
Ну как же. На стеке лежат адреса подпрограмм, переход на них осуществляется командой RET. А любое пришедшее прерывание сразу затрёт адрес, как минимум, своим адресом возврата.
Вроде дошло, спасибо!
Может тогда при разрешенных прерываниях в процедуре прерывания вначале сохранять кусок стека, а затем в конце перед выходом восстанавливать?
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)