Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Вт апр 23, 2024 16:29

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 117 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8  След.
Автор Сообщение
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вс май 03, 2015 22:10 
Не в сети

Зарегистрирован: Пн янв 07, 2013 22:40
Сообщения: 2141
Благодарил (а): 8 раз.
Поблагодарили: 74 раз.
mgw писал(а):
а как осуществляется компиляция (запись непосредственно по HERE) команды CALL и её аргумента? Судя по всему это делает слово COMPILE,

Это так?
Получается, что длина цепочки байтов в CALL и аргумента всегда одинакова?

Вроде так. Так как COMPILE, это низкоуровневое слово, а необходимую цепочку слов и аргументов её обработки создают
более "высокоуровневые" слова через механизм CREATE DOES> или с предопределённым заранее поведением и построением
типа IF ELSE ... (IF, кстати, можно сделать не компилируемым классически структуры слова в кодовое пространство, а с тремя аргументами на стеке - флаг, адрес_перехода_по_невыполнению_условия, адрес_перехода_по_выполнению_условия)

P.S. Вроде по классике так (Баранов, Ноздрунов), а как это варьируется в Fork автор подскажет или соответствующие топики форума.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вс май 03, 2015 22:26 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
mgw писал(а):
Судя по всему это делает слово COMPILE,

да

mgw писал(а):
Получается, что длина цепочки байтов в CALL и аргумента всегда одинакова?

что имеется ввиду под аргументом?

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Пн май 04, 2015 16:16 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
Наконец то заработали слова, которые ведут компиляцию шитых слов в свободное адресное пространство.
Код:
// Произведем компиляцию вызовов D-шной функции в область
// памяти выделенной командой:
//  uint[100] kdf;         // Сюда будем компилировать код
void t5() {   // : t5 ' exec_D COMPILE, ` exec_D COMPILE, RET, ;
   asm {      naked;
      call SP_dup;    lea EAX, exec_D;   call h_COMPILEzpt;
      call SP_dup;    lea EAX, exec_D;   call h_COMPILEzpt;
      call h_RETzpt;
      ret;
   }
}

// Выполним полученный код, через стандартный EXECUTE
void* t66() { return gpcb.acdf; }
void t6() {
   asm {   naked;
      call SP_dup;
      call t66;  // Взять адрес буфера, куда вели компиляцию
      call f_EXECUTE;
      ret;
   }
}



Настоящий, хоть и маленький, компилятор генерирует машинные команды, которые выглядят как обычные функции!!!

Следующий шаг - словарная статья. Пока только понял, что в ней точно есть:
Длина|Строка|0| ..... а вот, что дальше, это вопрос.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Пн май 04, 2015 22:36 
Не в сети
Аватара пользователя

Зарегистрирован: Вт мар 20, 2007 23:39
Сообщения: 1261
Благодарил (а): 3 раз.
Поблагодарили: 19 раз.
mgw писал(а):
Следующий шаг - словарная статья. Пока только понял, что в ней точно есть:
Длина|Строка|0| ..... а вот, что дальше, это вопрос.

В общем случае:
Поле связи | Поле флагов | Поле имени | Поле кода | Возврат
Поле связи - это ссылка на предыдущее слово в списке слов/словаре. Т.е. все слова в словаре - это односвязный список.
Флаги: признак немедленного исполнения. В разных системах могут быть дополнительные флаги.
Поле имени - обычно c-строка (первый байт - счетчик, дальше символы имени).
Код - сам код слова. Цепочка вызовов других слов или машинный код.
Код возврата - обозначет конец подпрограммы и безусловный переход по следующему адресу в стеке вовзратов. 0xC3

_________________
Cтоимость сопровождения программного обеспечения пропорциональна квадрату творческих способностей программиста.
Роберт Д. Блисc


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вт май 05, 2015 16:25 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
mgw писал(а):
Следующий шаг - словарная статья. Пока только понял, что в ней точно есть

ну, есть вот что, может поможет?

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Ср май 06, 2015 00:14 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
Всё оказалось заметно сложнее, чем я себе представлял. Реализовать сразу в полном объёме концепцию словарей Форка проблематично. Тут я больше склоняюсь в сторону Hishnik. Думаю сделать вначале простейший словарь, что бы завести цикл поиска-компиляции новых слов, а потом уже на их базе раскручивать систему дальше.

Сейчас у меня возникла другая проблема.

Hard слова у меня определены средствами D

void h_dup() {
asm {
.............
}
}
Адрес полученного кода "где то там", совсем не в том месте где мне надо, а надо мне сразу же за полем LINK (LFA) в словарной статье. Вижу 4 способа:
1 - Вкомпилировать ещё один CALL с адресом перехода на готовое hard слово
2 - Вкомпилировать JMP (сэкономить на передергивании стека)
3 - копирнуть функцию, как набор байтов в нужное место (муторно и не красиво)
4 - использовать директивы inline asm типа, db, ds и т.д. (правда ещё не проверил, реально ли это).

По логике 4 вариант самый правильный, надо мне его проверить.

Пытаюсь шить словарь. Словарная статья (пока на этапе старта упрощена до предела)
[len][Имя][0][len][IMM=BYTE][LFA=CELL]CALL,CALL .... RET

Пока думаю, какой из 4 способов применить.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Ср май 06, 2015 03:45 
Не в сети
Administrator
Administrator
Аватара пользователя

Зарегистрирован: Вт май 02, 2006 22:48
Сообщения: 7960
Благодарил (а): 25 раз.
Поблагодарили: 144 раз.
А если все-таки сама словарная структура и функции в разных местах? Тогда у слова появляется единственный адрес, на который надо перейти для его реализации, но его определить как раз просто &h_dup().
Тогда будет
[len][Имя][0][len][IMM=BYTE][LFA=CELL] jmp [&h_dup]


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Ср май 06, 2015 18:51 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
Код:
// (LIT)
void f_s_LIT_s() {
   asm {      naked;
      pop EBX;
      lea EBP,[EBP-CELL];
      mov dword ptr SS:[EBP],EAX;
      mov EAX,dword ptr DS:[EBX];
      lea EBX,[EBX+CELL];
      jmp EBX;
   }
}

// (CONST)
void f_s_CONST_s() {
   asm {      naked;
      lea EBP,[EBP-CELL];
      mov dword ptr SS:[EBP],EAX;
      pop EBX;
      mov EAX,dword ptr DS:[EBX];
      ret;
   }
}


Не пойму, два разных определения, делают одно и тоже. Или все таки есть отличия?


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Ср май 06, 2015 18:55 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
mgw писал(а):
Или все таки есть отличия?

отличия есть
первое возвращает значение, лежащее за call(на это определение), а затем передает управление на код, расположенный за значением литерала.
Второе возвращает значение и делает ret (выход на уровень выше)

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Ср май 06, 2015 19:05 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
Понял, спасибо за оперативность.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вс май 10, 2015 13:43 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
После длительного "топтания на одном месте" удалось немного продвинутся вперед. Основная трудность, это тот факт, что hard слава ассемблерные. Я не привык к манипуляции такими словами. Что бы проверить работу такого слова, надо переходить в режим Forth (а это фактически только отладчик ollydbg.exe). Так же, до недавнего момента, я пользовался готовыми словами Олега из виртуальной машины форка, но т.к. словарная статья изменилась, часть слов с форка, имеющие отношение к словарной статье уже не подходят. По этому очень много времени ушло на осознание и проверку слова COMPILE. Сейчас, я почти "подготовил" основные блоки (WORD CREATE COMPILE FIND EXECUTE STATE HERE CONTEXT), для того, что бы создать и запустить цикл чтения входного символьного потока, разбор их словом WORD и дальнейшею компиляцию или выполнение. Обычно такой цикл уже пишется на Форте, но у меня ещё нет слов ветвления, по этому предполагаю написать такой цикл на asm, благо я освоил команды ассемблера "условные переходы"

Последний "шедевр":
"CREATE ABC TCW HERE DUMP ABC" - Данная строка разбирается в "экспериментальном" ассемблерном цикле, где CREATE ABC - создает пустую словарную статью, TCW - при помощи COMPILE внутри себя шьёт в тело ABC несколько готовых слов и команду ret (используя RET,). HERE DUMP - это просто проверка, и в конце ABC выполняется как полноценное готовое слово.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Пн май 11, 2015 08:52 
Не в сети

Зарегистрирован: Сб май 06, 2006 12:01
Сообщения: 959
Откуда: Украина, Харьков
Благодарил (а): 2 раз.
Поблагодарили: 7 раз.
mgw писал(а):
но у меня ещё нет слов ветвления
см. тут: Баранов Ноздрунов "Язык Форт и его реализации"

_________________
With best wishes, in4.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Пн май 11, 2015 20:44 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
Получившиеся архитектура.

Контекст процесса (набор указателей на буфера стеков и кодофайла, TIB и т.д.)
хранится в глобальной памяти

Код:
// Контекст Fotrh процесса
struct NPcb {
   pp    csd;                // указатель на начало стека SD
   pp    csr;                // указатель на начало стека SR
   pp    csc;                // указатель на начало стека SC
   pp   acdf;               // указатель на начало кодофайла
   pb    here;                // указатель начала свободной области кодофайла
   pp    latest;               // указатель на аоследнее скомпилированное слово
   pp   context;            // указатель на LFA слова с которого дальше пойдет поиск
   pp   state;               // текущее состояние компиляции 0=интерпретация
   byte imm;               // запомнить состояние IMM в последнем FIND

   ps   In;                     // указатель на место интерпретации в вход. буфеpе
    ps   Tib;                // указатель на сам входной буфеp
   int dlTib;               // Размер строки прочитанной в Tib
   // Регистры сохранения состояния
   pp saveEBP;          // Место под EBP форта
   pp saveEAX;          // Место под EAX форта
   pp saveESI;          // Место под ESI форта
   pp saveEDI;          // Место под EDI форта
}

NPcb gpcb;                  // Глобальное определение блока управления
pb   kdf;                  // Сюда будем компилировать код
pp  stSD, stSR, stSL;         // Указатели на стеки
ubyte[1000] tib;            // Буфер строки для текстового разбора



initForth(); - Выделить в хипе буфер под кодофайл (куда ведется компиляция по here),
выделить буфера под стеки данных и дополнительный. Стек возвратов общий с D. После
выделения все регистры Форта сохранить в контексте.

Код:
void initForth() {
   kdf = cast(pb)(new uint[1000]).ptr;      // Изготовим кодофайл на 1000 адр
   NPcb npcb = gpcb;                       // Копирнем в локальный, что бы иметь доступ с asm
   const sizeSt = 100;                // По 100 CELL на каждый стек
   stSD = cast(pp)(new uint[sizeSt]);      // Запомнить начало области SP в глобальной переменной
   npcb.csd = stSD + sizeSt - 1;         // Запомнить вершину стека SP в контексте (конец буфера)
   
   stSL = cast(pp)(new uint[sizeSt]);      // Запомнить начало SP в глобальной переменной
   npcb.csc = stSL + sizeSt - 1;         // Запомнить вершину SL в контексте (конец буфера)
   
   npcb.here = kdf;                  // HERE на начало буфера
   npcb.acdf = cast(pp)kdf;            // Указатель на кодофайл
   npcb.Tib = cast(ps)&tib;            // Указатель на входной буфер текста
   npcb.In = cast(ps)&tib;                 // указатель смещения во входном буфере
   asm {
      align 4;
      // Сохраним регистры D
      push EBX; push ESI; push EAX; push ECX;   push EDX; push EBP;
      // --------------------
      // В ESI запомним указатель на доп стек SL
      lea EAX, npcb.csc.offsetof[npcb]; // в локальной копии ищем нужные указатели на буфера
      mov ESI,  DS:[EAX];
      // Из контекста возьмем указатель на стек данных ...
      lea EAX, npcb.csd.offsetof[npcb];
      mov EAX,  DS:[EAX];
      call SP_set; // ... и инициализируем его
      mov EAX, ESI;   call LP_set; // Стек дополнительный для Форк
      // Сохраним состояние регистров Форта после инициализации в контексте
      mov ECX, EBP;   // Жертвуем ECX, что бы успешно сохранить EAX, EBP, ESI, EDI
      pop EBP;
      mov npcb.saveEAX.offsetof[npcb], EAX;
      mov npcb.saveEBP.offsetof[npcb], ECX;  // Сохраним запомненный EBP
      mov npcb.saveESI.offsetof[npcb], ESI;
      mov npcb.saveEDI.offsetof[npcb], EDI;
      // ----------------------
      // Восстановим регистры D
      pop EDX; pop ECX; pop EAX; pop ESI; pop EBX;
   }
   gpcb = npcb; // Сохраним контекст в глобальной памяти
   
   // определение HARD слов
   CreateVocItem(cast(char*)"\3EXD".ptr,       cast(pp)&exec_D,       &gpcb.context);
   CreateVocItem(cast(char*)"\2T5".ptr,       cast(pp)&t5,          &gpcb.context);
   CreateVocItem(cast(char*)"\3TCW".ptr,       cast(pp)&TestCompileWord, &gpcb.context);
   CreateVocItem(cast(char*)"\4DROP".ptr,       cast(pp)&h_DROP,       &gpcb.context);
   CreateVocItem(cast(char*)"\4OVER".ptr,       cast(pp)&h_OVER,       &gpcb.context);
   CreateVocItem(cast(char*)"\1+".ptr,       cast(pp)&h_PLUS,       &gpcb.context);
    и т.д.


Функция evalForth - позволяет полностью интерпретировать/компилировать одну
строку, без потери контекста, т.к. он сохраняется и восстанавливается из глобальной
памяти.

Код:
void evalForth(string str) {
   gpcb.dlTib = str.length;      // Запишем длину строки в gpcb
   gpcb.In = cast(ps)gpcb.Tib;     // указатель смещения во входном буфере
   // Копирнем строку из входного параметра в буфер
   for(int i; i != str.length; i++) tib[i] = cast(ubyte)str[i];
   NPcb npcb = gpcb;   // Копирнем контекст в локальную обл. что бы asm её видел
   asm {
      align 4;
      // Сохраним регистры D
      push EBX; push ESI; push EAX; push ECX; push EDX; push EBP;
      // --------------------
      // Востановим регитры F форта, это состояние после Init или пред. Eval
      mov EAX, npcb.saveEAX.offsetof[npcb];
      mov ESI, npcb.saveESI.offsetof[npcb];
      mov EDI, npcb.saveEDI.offsetof[npcb];
      mov EBP, npcb.saveEBP.offsetof[npcb];
      
      call f_inter;   // Это главный цикл компиляции/интерпретации.
      
      // Сохраним F форта
      mov ECX, EBP; // Жертвуем ECX, что бы успешно сохранить EAX, EBP, ESI, EDI
      pop EBP;      // Востановим фрейм локальных переменных D
      mov npcb.saveEAX.offsetof[npcb], EAX;
      mov npcb.saveEBP.offsetof[npcb], ECX;  // Сохраним запомненный EBP
      mov npcb.saveESI.offsetof[npcb], ESI;
      mov npcb.saveEDI.offsetof[npcb], EDI;
      // ----------------------
      // Восстановим регистры D
      pop EDX; pop ECX; pop EAX; pop ESI; pop EBX;
   }
   gpcb.saveEBP = npcb.saveEBP;   // Возможность работы с PCB (контекст) переменными в ASM
   gpcb.saveEAX = npcb.saveEAX;   // Возможность работы с PCB (контекст) переменными в ASM
   gpcb.saveESI = npcb.saveESI;   // Возможность работы с PCB (контекст) переменными в ASM
   gpcb.saveEDI = npcb.saveEDI;   // Возможность работы с PCB (контекст) переменными в ASM
}


В результате возможна работа:

Код:
void main() {
   initForth();
   writeln(toCON("Сохраняю набор цифр в стеке данных форта"));
   evalForth("4 3 1");
   writeln(toCON("Забираю этот набор из форта"));
   evalForth(". . .");
   writeln(toCON("Компилирую новые слова"));
   evalForth(" : TEST_PLUS + . ; : Test2 DUP + . ; : Утроение DUP DUP + + . ;");
   writeln(toCON("Проверяю созданные слова"));
   evalForth("2 3 TEST_PLUS 7 Test2   -3 Утроение");
}



Результат работы:

Код:
g:\qte>dmd asm3 asc1251    // Компиляция проекта

g:\qte>asm3                // Запуск проекта
Сохраняю набор цифр в стеке данных форта
Забираю этот набор из форта
1
3
4
Компилирую новые слова
Проверяю созданные слова
5
14
-9


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вт май 12, 2015 05:58 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 5062
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 23 раз.
Поблагодарили: 63 раз.
Сильно в подробности не вдавался (некогда), но замечание сделаю
mgw писал(а):
pp    csd;                // указатель на начало стека SD

очень неудобно, когда используются незнакомые имена, в СПФе, это было бы S0 в Win32Forth - SP0
и т.п. что такое csd не понятно, впрочем, как и дальше.

_________________
Мне бы только мой крошечный вклад внести,
За короткую жизнь сплести
Хотя бы ниточку шёлка.
fleur


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения: Re: Forth на inline asm. Это реально?
СообщениеДобавлено: Вт май 12, 2015 16:52 
Не в сети

Зарегистрирован: Ср фев 17, 2010 18:10
Сообщения: 323
Откуда: Тверь
Благодарил (а): 13 раз.
Поблагодарили: 11 раз.
mOleg писал(а):
очень неудобно, когда используются незнакомые имена


Полностью согласен. Буду работать над этой проблемой. По правильному, на SPF-Fork надо писать полное техническое описание. Штука сложная, сразу и не понятно где и что.

Создал связку CREATE ... DOES> Причем сделал её уже средствами форта используя (JOIN) и (DOES). Соответственно определил CONSTANT, VARIABLE.

Интересная получается штука. Ядро - это аsm слова из SPF-Fork, собранные в "кучу"
циклом на asm, который встроен как функция в D программу.

Классический пример DUP:
// Определение в asm
Код:
// DUP ( n --> n n )
private void h_DUP() {
   asm {      naked;
      lea EBP,   [EBP-CELL];
      mov [EBP],   EAX;
      ret;
   }
}

// Подвязка в словарь
Код:
CreateVocItem(cast(char*)"\3DUP".ptr, cast(pp)&h_DUP,  &gpcb.context);


// Пример использования DUP внутри другого слова
Код:
// \ компилировать безусловный переход на указанный адрес √
// : JUMP, ( addr --> )  0xE9 B, <resolve ;
private void h_JUMPzpt() {      
   asm {      naked;
      call h_DUP; mov EAX, 0xE9;
      call h_Bzpt;
      call f_L_resolve;
      ret;
   }
}


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 117 ]  На страницу Пред.  1, 2, 3, 4, 5, 6, 7, 8  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 19


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB