Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Виртуальные машины, на языках типа С/Pascal, структуры и реализация

9.0K
06 февраля 2005 года
Bragg
13 / / 06.02.2005
Я выбрал трехадресный код, но язак высокого уровня позволяет более изощренные способы представления ВМ. Вот и стоит вопрос скорости интерпритации и программирования.
Кто что может сказать по этому поводу.
391
07 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
Я выбрал трехадресный код,


А что такое трехадресный код? Стек, даные, код?:???:

9.0K
08 февраля 2005 года
Bragg
13 / / 06.02.2005
Цитата:
Originally posted by Archie

А что такое трехадресный код? Стек, даные, код?:???:



трехадресный код - это один два три
один - операия
два - аргумент
три - аргумент
(может быть и четыре - это результат)
можно представить мнемокод как тройки

к примеру :
op arg1 arg2 res
MOV a, 100
ADD a, b
...
вся виртуальная машина - это и есть таблица таких троек или четверок, в яве к примеру не так, там набор этих данных реализуется в стеках.
это дело можно компилировать в асме если транслировать те же самые четверки мнемокод асма.

10.0K
12 февраля 2005 года
n-coder
2 / / 12.02.2005
1. а какие команды у вас есть и сколько их (mov, add, что ещё?)?
2. c какими регистрами можно использовать команды, а с памятью как работать?
3. сколько битов идёт на описание команды, первого операнда, второго в байт-коде, его структура?
9.0K
15 февраля 2005 года
Bragg
13 / / 06.02.2005
Как я понимаю , виртуальная машина - это набор состояний : регистров, флагов , структур(своих придуманных) и т.д. Ведь все это виртуальное, не машинное. Я могу сам понапридумывать что захочу. Но так повелось : трехадресный код, бинарные операторы, операции.
Кроме mov add они у меня называются plus assign
есть еще += -= /= ++ -- и т.д.
есть sin cos pow и т.д.
а есть
для работы с представлением(таблицей четверок): JMPF, JMP, PUSH, POP(для работы с программным стеком), CALL, RET.
Все эти команды работают с МОЕЙ виртуальной машиной.
391
15 февраля 2005 года
Archie
562 / / 03.02.2005
По-моему скорость интерпретации будет зависить от того, насклько расширеный набор комманд у VM. Можно создать универсальную машину с RISC, ее будет очень просто интерпретировать, но скорость интерпретации скорее всего будет невысокой.
Например, организация стека - в нем можно держать либо "чистые данные" и не озадачивать машину типами и проч., что позволит написать глупость вроде:
pushf 3.1415926 ; push 4-bytes float value
pushd 1234 ; push 4-bytes integer
addd ; add 4-bytes integers

Можно сделать более универсально:
push 3.1415926 ; push float
push 1234 ; push integer
add ; add float+integer => float

Что усложнит интерпретацию (немного), но код скорее всего работать будет быстрее.

Еще пример - работа с переменными:

pushd Var1 ; push 4-bytes pointer
rtif ; replace 4-bytes address by
; float value, pointed by this
; address
pushf 1.23
mulf ; mul two floats
pushd Var2 ; push 4-bytes pointer
popif ; pop a float to this pointer

А можно и проще:
push Var1
push 1.23
mul ; Машина сама загрузит переменную
; и преобразует типы
pop Var2

Можно ввести и регистры общего назначения помимо стека, но при этом интерпретация будет медленнее и сложнее - куча комманд, стек-регистр и все такое...
Так что, все зависит от конкретной задачи, для которой будет использоваться VM.
9.0K
15 февраля 2005 года
Bragg
13 / / 06.02.2005
ВМ - простая. (Математические выражения типа С).
Адресное пространство переменных, виртуальная таблица для структур(уже существующих, т.е. скрипт не позволяет описывать свои struct/class)
стек программы для создания подпрограмм.
динамических переменных нет, все статические.

все вроде просто. Критические(нескриптовые) подпрограммы вызываются по идентификаторам, собственно как и набор комманд типа ADD MULL
SIN ... таких комманд ~32 (+критические функции) типа sin cos ...

Пускай код скрипта уже транслированный будет 10000
троек, значит максимум на одну тройку для обработки потребуется (max)40 сравнений примерно, ну типа:
switch ( op )
case ADD:
case MUL:
...
все это дело должно работать в интерактивном режиме да еще и с трехмерной графикой.
Вообще это нечно на VRML похоже, только посерьезнее, скорее X3D.

------------------------------------------------
Кстати, может знаете, область видимости подпрограмм, как реализовать для статических переменных.
391
16 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
Пускай код скрипта уже транслированный будет 10000 троек, значит максимум на одну тройку для обработки потребуется (max)40 сравнений


Вот эти рассуждения я что-то не очень понял... :)

Ну вобщем подход один: выбираем опкод и интерпретируем его:
while ( working ) {
fetch_opcode (opcode);
switch ( opcode ) {
...
default:
invalid_opcode ();
}
}

Если переписать в асме, можно это проделывать очень быстро, если коды команд выстроены по порядку:

working:
call fetch_opcode
cmp ax, 0
jz opcode_0x00
dec ax
jz opcode_0x01
dec ax
jz opcode_0x02
...

jmp working

Можно ввести статистику комманд, что несколько ускорит интерпретацию (например, после комманд типа cmp с очень большой вероятностью следуют комманды перехода и т.п.)

Цитата:

Кстати, может знаете, область видимости подпрограмм, как реализовать для статических переменных.



Т.е. нужно реализоват статические переменные в подпрограммах?
Ну, в Java это реализуется с помощью таблицы статических переменных. Такая таблица имеется для каждого метода (подпрограммы) класса. Соответственно, строится эта таблица в процессе компиляции. Т.е. есть глобальная таблица полей (для всего класса) и таблицы для методов.
Если код и данные совместить (использовать одно адресное пространство памяти), то можно выделять участки памяти в коде для статических переменных:

proc Foo

; Var = Var - 1
push Var
dec
pop Var

ret ; return

Var db 0x00

end

9.0K
17 февраля 2005 года
Bragg
13 / / 06.02.2005
насчет опкодов: опкод - адрес на функию, т.к. тройки фиксированные, то функция с тремя параметрами(третий - результат).

вопрос созрел:
сос статическими переменными понятно - это друг глобальных переменных только со своей областью видимости, НО а как быть с динамическими локальными переменными, (за одно формальными, фактическими) все через стек?
391
18 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
насчет опкодов: опкод - адрес на функию, т.к. тройки фиксированные, то функция с тремя параметрами(третий - результат).


Т.е. структура инсрукции такая:
<opcode><arg1><arg2><res> = 4 байта ?
Или про какие тройки речь? ;)

Цитата:

вопрос созрел:
сос статическими переменными понятно - это друг глобальных переменных только со своей областью видимости, НО а как быть с динамическими локальными переменными, (за одно формальными, фактическими) все через стек?



А что, без них никак?
Ну можно ввести native-инструкции выделения/освобождения памяти:

push 1234
call native malloc ; теперь в стеке аддрес на область памяти в 1234 байта
call native free ; освобождаем

Можно и через стек, если есть возможность общаться с ним не только push/pop, но и как с обычной памятью (как это в x86 делается).

9.0K
18 февраля 2005 года
Bragg
13 / / 06.02.2005
Да, именно такие тройки(четверки).

А динамические/автоматические именно так, или CALL или runtime stack. Но вот область видимости на уровне блоков(как в С/C++). Деревом чтоли делать?
9.0K
18 февраля 2005 года
Bragg
13 / / 06.02.2005
Но у меня не 4 байта, а фиг знает сколько,
аргументы, и res у меня структурами, а там и массивы и флоаты и инты и векторы, может еще что нибудь будет.
391
18 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
Да, именно такие тройки(четверки).

А динамические/автоматические именно так, или CALL или runtime stack. Но вот область видимости на уровне блоков(как в С/C++). Деревом чтоли делать?



Область видимости проверяется на этапе компиляции, а локальные переменные заменяются реальными адресами. Или ты хочешь сохранить оригинальные имена переменных в байт-коде?
Если есть код типа:
...
int x;
... // -------------- здесь видна только переменная x
if ( x == 0 ) {
int y;
... // ------------ здесь видны x и y
}
... // ----- здесь опять только x


то компиллятор сгенерирует две локальные переменные в одном блоке (например, процедуре), а область видимости проверит на этапе компиляции, как я уже сказал. Правда многие "умные" компиляторы заменят такие переменные стеком или регистрами.

9.0K
18 февраля 2005 года
Bragg
13 / / 06.02.2005
в хеш таблице хранятся адреса, на этапе компиляции имена хешируются и смотрятся в хеш таблице, а вместо переменных "а" в <arg1/2> заносится ее адрес.

Байт код не генерируется сразу все транслируется в тройки и там ВМ крутит их.


ну а если рекурсия?
391
18 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
... ну а если рекурсия?



А статические переменные при рекурсивном вызове не сохраняются :)
Выполни такой код:
//
void foo ( bool stop ) {
static int x = 0;
x++;
if ( !stop )
foo ( true );
printf ("%d\n", x);
}

foo ( false );
//

Если ты ожидаешь на выходе получить "2 1", то это будет для тебя сюрпризом ;)

9.0K
18 февраля 2005 года
Bragg
13 / / 06.02.2005
ну ну, вот мне и нужно , что бы оно вывело 1 1
а не 2 2(как я понимаю на один адрес ссылается)
391
18 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
ну ну, вот мне и нужно , что бы оно вывело 1 1
а не 2 2(как я понимаю на один адрес ссылается)


Ну так не делает ниодин компилятор - всегда будет 2 2 :)

9.0K
18 февраля 2005 года
Bragg
13 / / 06.02.2005
потомучто static.
статические переменные - несложно реализовать.
Динамические, вот в чем вопрос.
----------
И как быть с областью видимости.
Когда создается static переменная, то можно если a
делать a1 во вложенных блоках
{static int a}{static int a(a1)}
но а если динамическая, с областью видимости?
391
21 февраля 2005 года
Archie
562 / / 03.02.2005
Цитата:
Originally posted by Bragg
потомучто static.
статические переменные - несложно реализовать.
Динамические, вот в чем вопрос.
----------
И как быть с областью видимости.
Когда создается static переменная, то можно если a
делать a1 во вложенных блоках
{static int a}{static int a(a1)}
но а если динамическая, с областью видимости?



Я не пойму в чем проблема.
Динамические переменные - это указатели на область памяти. В чем трудность-то?
А область видимости проверяй во время компиляции:

 
Код:
namespace A {
  int x;
  namespace B {
    int x;

    A.x = 10;
    B.x = 20;
  }
}


ну или используй какой другой синтаксис.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог