ПО, ЭВМ и АСУ из Таможенного Союза

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » Проект "Виртуальные машины" » Некоторые требования к виртуальным машинам


Некоторые требования к виртуальным машинам

Сообщений 31 страница 48 из 48

31

Евгений написал(а):

Сильно ли влияет ли уровень ВМ на быстродействие?

Зависит от уровня абстракции и возможностей ВМ, например наличия JIT-компилятора.
Очень просто делается ВМ, где любая операция/конструкция представлена вызовом некоторой функции - соответственно будет замедление на передачу параметров.
Но и архитектуру ЭВМ тогда знать для ее реализации не нужно, никаких регистров процессора и т.п.
По быстродействию можно легко провести эксперимент.

Евгений написал(а):

И что важнее: скорость исполнения или совокупный показатель, объединяющий скорость трансляции и скорость исполнения?

Зависит от целевого применения. Обычно важнее совокупная скорость решения задачи. Где-то к скорости исполнения нужно прибавлять и скорость трансляции, а где-то и время разработки.

Отредактировано MihalNik (2022-06-15 16:14:33)

0

32

Лис написал(а):

Вон, в JavaScript с WebAssebmly виртуальная машина не умеет как следует в многопоточность, уже не первое десятилетие с этим мучаются.
А ведь не трудно было с самого начала подумать.

Многопоточность может быть оформлена вызовом подпрограмм.

Лис написал(а):

оно рушит возможность доказывания гарантий про код

Не рушит, а дробит.

0

33

Это не код, а набросок. Только для того, чтобы началась рождаться терминология. Добавлены варианты.

Терминология
Код:
#если_нет 	OPCODE_H
#макрос	  	OPCODE_H	

перечисл ОпКоды {
	
        СТОП = 0,       // - Остановка работы процессора
        // - Целочисленная арифметика
        цСЛОЖ = 2,       // - Сложение целых чисел
        цВЫЧ  = 3,       // - Вычитание целых чисел
        цУМН  = 4,       // - Умножение целых чисел
        цДЕЛ  = 5,       // - Деление целых чисел
        цОСТ  = 6,       // - Остаток от деления
        цИНК  = 7,       // - Инкремент
        цДЕК  = 8,       // - Декремент
 /*     ПЛЮС1 = 7,       // - Инкремент (альтернатива)
        МИНУС1 = 8,       // - Инкремент (альтернатива)
*/        // - Логические операции
        И   = 9,       // - Логическое И
        ИЛИ = 10,       // - Логическое ИЛИ
        НЕ  = 11,      // - Логическое НЕ
        // - Вещественная арифметика
        вСЛОЖ = 12,      // - Сложение вещественных чисел
        вВЫЧ = 13,      // - Вычитание вещественных чисел
        вУМН = 14,      // - Умножение вещественных чисел
        вДЕЛ = 15,      // - Деление вещественных чисел
};
#к_если    //OPCODE_H

Код:
 
#если_нет 	OPCODE_H
#макрос	  	OPCODE_H	
 
перечисл ОпКоды {
	
        опСТП = 0,       // - Остановка работы процессора
        // - Целочисленная арифметика
        опСЛЖ = 2,       // - Сложение целых чисел
        опВЧТ  = 3,       // - Вычитание целых чисел
        опМНЖ  = 4,       // - Умножение целых чисел
        опДЛН  = 5,       // - Деление целых чисел
        опОСТ  = 6,       // - Остаток от деления
        цИНКР  = 7,       // - Инкремент
        цДКР  = 8,       // - Декремент
 /*     ПЛЮС1 = 7,       // - Инкремент (альтернатива)
        МИНУС1 = 8,       // - Инкремент (альтернатива)
*/        // - Логические операции
        опИ   = 9,       // - Логическое И
        опИЛИ = 10,       // - Логическое ИЛИ
        опНЕ  = 11,      // - Логическое НЕ
        // - Вещественная арифметика
        опВ_СЛЖ = 12,      // - Сложение вещественных чисел
        опВ_ВЫЧ = 13,      // - Вычитание вещественных чисел
        опВ_МНЖ = 14,      // - Умножение вещественных чисел
        опВ_ДЛН = 15,      // - Деление вещественных чисел
};
#к_если    //OPCODE_H
Код:
#если_нет 	OPCODE_H
#макрос	  	OPCODE_H	
 
перечисл ОпКоды {
	
        опСТОП = 0,       // - Остановка работы процессора
        // - Целочисленная арифметика
        опСЛОЖЕНИЕ = 2,       // - Сложение целых чисел
        опВЫЧИТАНИЕ  = 3,       // - Вычитание целых чисел
        опУМНОЖЕНИЕ  = 4,       // - Умножение целых чисел
        опДЕЛЕНИЕ  = 5,       // - Деление целых чисел
        опОСТАТОК  = 6,       // - Остаток от деления
        цИНКРЕМЕНТ  = 7,       // - Инкремент
        цДЕКРЕМЕНТ  = 8,       // - Декремент
 /*     ПЛЮС1 = 7,       // - Инкремент (альтернатива)
        МИНУС1 = 8,       // - Инкремент (альтернатива)
*/        // - Логические операции
        опИ   = 9,       // - Логическое И
        опИЛИ = 10,       // - Логическое ИЛИ
        опНЕ  = 11,      // - Логическое НЕ
        // - Вещественная арифметика
        опВ_СЛОЖЕНИЕ = 12,      // - Сложение вещественных чисел
        опВ_ВЫЧИТАНИЕ = 13,      // - Вычитание вещественных чисел
        опВ_УМНОЖЕНИЕ = 14,      // - Умножение вещественных чисел
        опВ_ДЕЛЕНИЕ = 15,      // - Деление вещественных чисел
};
#к_если    //OPCODE_H

Отредактировано Евгений (2022-06-16 09:09:11)

0

34

Появились ли мысли, какую машину будем разрабатывать? Регистровую, стековую, комбинированную... Сколькиадресную...  Сколькибитную... Какой начальный набор команд?

0

35

Евгений написал(а):

Появились ли мысли, какую машину будем разрабатывать? Регистровую, стековую, комбинированную... Сколькиадресную...  Сколькибитную... Какой начальный набор команд?

Сначала пишем машину под компилятор.
С регистром адреса команд (т.е. не четырёх-адресную, а максимум трёх),
С регистрами общего назначения (штук 15 хватит, наверное по уши)
С регистром стека (чтобы было удобно делать рекурсивные функции),
С косвенной адресацией (чтобы можно было получать доступ к элементам массивов, хотя бы одномерных строк)

Расширяем её памятью.

Потом расширяем её вводом-выводом, для того, чтобы сделать web-сервер,

Затем таргетируем на неё компилятор ПОП,
либо пишем под неё по-аналогии с компилятором ПОП компилятор на русифицированном си

Затем пишем сайт/форум на российском языке (компилятора).

Арность элементов памяти = 2 (биты, а не триты, хотя было бы прикольно, но париться не хочется)
Разрядность памяти = 8 бит на байт
Длина регистров = 64 бит на регистр

не нужны команды для плавающей точки, наверное
нужен регистр флагов (арифметический перенос, флаг знака, флаг нулевого результата, + не помню что там ещё хранят)

нужна команда "выполнить аппаратную магию" (примерно как syscall), к ней пять расширений:
0) читать с потока ввода
1) писать в поток вывода
2) писать в поток ошибок
3) получить командную строку
4) получить переменные окружения

Таким образом всё нужное для компилятора и протокола CGI (common gateway interface) будет. Конечно, это не оптимально, зато быстро с точки зрения реализации.

На первом этапе многопоточность не делаем, потому что не умеем (и будем как авторы JavaScript).

Вообще говоря, на КуМире сайты делали, и CGI к нему прикручивали. Можно и этот подвиг повторить, но мне не нравится большое количество иностранных компонент в том решении.

Отредактировано Лис (2022-06-16 20:06:13)

0

36

Можно ещё сделать отдельный регистр, указывающий на блок с описанием памяти (списком блоков),
каждая из записей списка содержит адрес начала, длину, и вспомогательные флаги (какие-нибудь),
и пару системных вызовов - добыть блок (адрес, длина), избавиться от блока (адрес).

Ну и по аналогии, раз уж можно создавать блоки памяти, то сделать системные вызовы:
- получить права на запуск вложенных виртуальных машин
- создать вложенную виртуальную машину (адрес блока памяти)
- удалить машину
- отдать права на запуск виртуальных машин.

Вложенной виртуальной машине придавать начальный блок памяти,
а команда вызова системы будет передавать управление из вложенной виртуальной машины в эту виртуальную машину.

С параллельностью работы пока непонятно как (нужно прерывание "дочерняя машина закончила работу"?)

Отредактировано Лис (2022-06-16 21:00:55)

0

37

Разрядность стека я так понимаю тоже будет 64 бита, чтобы сохранять общие регистры? Какова разрядность команды без операндов, 32 бита? Будем делать поддержку 8-, 16-, 32-, 64- битных данных с набором арифметических операций и операций пересылки для каждого вида? Или 8 и 16- ти битные данные будут лежать в 32- х битных ячейках?

0

38

Евгений написал(а):

Разрядность стека я так понимаю тоже будет 64 бита, чтобы сохранять общие регистры?

Мне непонятен вопрос. Стек - это кусок памяти. Все куски памяти состоят из байтов.
У регистра стека может быть "выравнивание", то есть если все команды изменяют его на 8 байт, то значение регистра всегда будет кратно 8-ми.
Но нельзя сказать, что это его "разрядность".

Евгений написал(а):

Какова разрядность команды без операндов, 32 бита?

Вот вообще без разницы. Ну пусть будет 64 бита тоже, там же можно складывать номера регистров, а они короткие (4 бита, к примеру).

Евгений написал(а):

Будем делать поддержку 8-, 16-, 32-, 64- битных данных с набором арифметических операций и операций пересылки для каждого вида?

Не вижу смысла. Каждому символу в строке по 8 байтов!

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

Евгений написал(а):

Или 8 и 16- ти битные данные будут лежать в 32- х битных ячейках?

Это можно позднее сделать (чтобы восьмибитное обрабатывалось восьмибитно и так далее), как опцию арифметико-логического устройства ("Экономное АЛУ").

0

39

Лис написал(а):

Мне непонятен вопрос. Стек - это кусок памяти. Все куски памяти состоят из байтов.
У регистра стека может быть "выравнивание", то есть если все команды изменяют его на 8 байт, то значение регистра всегда будет кратно 8-ми.
Но нельзя сказать, что это его "разрядность".

В момент вызова подпрограммы в стеке сохраняются значения регистров. Если, кроме значений регистров мы в стек больше ничего писать не планируем, то его будет удобно реализовать в виде массива 64-битных значений, чтобы на каждом шаге не заниматься приведением типов. Если, теоретически, мы планируем писать туда что-то ещё (не 64-битное), то его поведение уже более сложное. Можно использовать массив и 8-битных значений, но есть вероятность проиграть в быстродействии.

Отредактировано Евгений (2022-06-17 07:06:46)

0

40

Евгений написал(а):

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

Делая интерпретатор мы заранее принимаем, что быстродействие нас не интересует.

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

Но да, можно стек и отдельно сделать в своём отдельном адресном пространстве.
А можно и так и так на выбор.

0

41

Можем ли мы в ВМ отказаться от строк из 8-битных символов? То есть в байт-коде строки будут представлены исключительно в виде массива 16-битных символов. Это не значит, что будет невозможна обработка обычных 8битных символов, просто работа с ними и с кодировками будет вынесена в библиотеку. Такой подход упрощает ядро ВМ, сохраняя поддержку кириллицы.

0

42

Евгений написал(а):

Можем ли мы в ВМ отказаться от строк из 8-битных символов?

А зачем в ВМ вообще строки? ВМ либо с отдельными байтами работает, либо нет.
А уж как там эти байты будут использоваться, это языка программирования проблема (точнее его реализации), не?

Причём даже если все операции 64-х битные, работать с байтами это не помешает,
как в случае если адресация побайтовая (но будет неудобно, да, надо будет загружать регистр, маскировать биты, и выгружать регистр целиком, изменив в нём только один байт)
так и даже если адресация с бо́льшим шагом (только работать с байтами станет ещё неудобнее).

Нет ведь проблем в современных машинах изменять отдельные биты в памяти?

Поскольку в Intel есть аппаратная поддержка работы с частями регистров, то
предлагаю в ВМ сделать так же (команды работы с 64, 32, 16, 8 битами).
Можно будет несложным образом отобразить команды ВМ на команды процессора.

В архитектуре Arm64:
«Each register can be used as a 64-bit X register (X0..X30), or as a 32-bit W register (W0..W30). These are two separate ways of looking at the same register. »

«There is a separate set of 32 registers used for floating point and vector operations. These registers are 128-bit, but like the general-purpose registers, can be accessed in several ways. Bx is 8 bits, Hx is 16 bits, Sx is 32 bits, Dx is 64 bits, and Qx is 128 bits. ... The name you use for the register determines the size of the calculation.»

Отредактировано Лис (2022-06-22 17:45:29)

0

43

Для целочисленных типов данных всё рассуждения верны. И пока мы жонглирует символами по-отдельности, мы можем это делать аналогично целым типам. Но нам нужно уметь хранить строки, выводить их в стандартный поток вывода, читать... И для этих целей имеет смысл использовать системные функции, встроенные в ОС. Функции эти могут работать либо с однобайтными строками, либо с двухбайтными. Я предлагаю в основе оставить двухбайтные. А дальше пусть уже в языке решаются проблемы преобразований.

0

44

Евгений написал(а):

имеет смысл использовать системные функции, встроенные в ОС

Это тоже не проблемы виртуальной машины. Системная библиотека языка знает какие там функции в ОС, и сопоставляет их функциям языка.
Виртуальная машина должна, конечно, предоставлять какие-то устройства для ввода-вывода,
но я не думаю, что она это должна делать прям на уровне вывода строк.

Например, можно предоставлять устройство "стандартный ввод-вывод", которое содержит три потока (байтов), набор переменных окружения и параметры командной строки.

Или всё через иерархическую (файловую) систему, то есть, директории (пути) + массивы байтов.

Мы тут пытаемся сэмулировать шины (PCIe), но я к моему стыду, не знаю, как именно они работают и как их эмуляция сделана в QEMU

Отредактировано Лис (2022-06-22 18:00:45)

0

45

Есть ещё один вопрос, что будем делать с ошибками времени исполнения? Ошибки переполнения, деление на ноль... Просто пишем в поток ошибок? Я сейчас имею в виду не механизм, который мы представляем программисту для обработки ошибок, а случай, когда нужно пропущенную ошибку обработать по умолчанию.

0

46

Евгений написал(а):

Ошибки переполнения, деление на ноль...

А машина Тьюринга что с ними делает? У нас по сравнению с неё только одно дополнительное ограничение - исчерпание памяти (ленты).
В этом случае предлагаю прекращать работу виртуальной машины, и всё.

Хотя да, у нас есть дополнительные устройства
- сумматоры и аппаратная схема деления.

Они могут выставлять флаги в регистр флагов - переполнения и деления на ноль.

Отредактировано Лис (2022-06-22 18:20:19)

0

47

Про Intel:

«Interrupt 4—Overflow Exception (#OF)

Exception Class Trap.

Description

Означает, что возник overflow trap при выполнении инструкции INTO. Инструкция INTO проверяет состояние флага OF регистра EFLAGS. Если OF флаг установлен, генерируется overflow trap.

Некоторые арифметические операции (такие как ADD и SUB выполняющиеся над любыми знаковыми и беззнаковыми числами устанавливают флаги OF и CF регистра EFLAGS для индикации знакового переполнения или беззнакового переполнения соответственно. При выполнении арифметических на знаковых операндах, флаг OF может быть проверен напрямую или инструкция INT0 может быть использована. Преимущество инструкции INT0 в том, что при переполнении, обработчик исключения может быть вызван автоматически для обработки overflow состояния.»

Про Arm64 (там такого нет):
https://community.arm.com/arm-community … w-from-mul
https://gcc.gnu.org/onlinedocs/gcc/Inte … ltins.html

https://stackoverflow.com/questions/545 … ow-test-so

А Go Lang такая же проблема, как в языке Си.

Отредактировано Лис (2022-06-22 19:27:39)

0

48

Выставить и проверить флаги после каждой операции не сложно. Эмулировать прерывание по факту переполнения тоже не сложно. Как дать возможность языку осмысленно обработать такие прерывания, тут есть над чем подумать. Обработка исключений в виртуальной машине по умолчанию и возможности, которые ВМ предоставит языку для обработки исключений требуют проработки.

0


Вы здесь » ПО, ЭВМ и АСУ из Таможенного Союза » Проект "Виртуальные машины" » Некоторые требования к виртуальным машинам