Таблица лидеров - JIT скомпилировано (чем ниже, тем лучше)
- es1024 - 81,2 балла (включая работающий компилятор!)
- Кит Рэндалл - 116 очков
- Элл - 121 очко
Таблица лидеров - Интерпретируется (чем ниже, тем лучше)
- Мартин Бюттнер - 706654 балла (где-то около 2 часов).
- криптих - 30379 баллов (97 секунд)
Ваша миссия, если вы решите принять ее, - написать наименьший возможный интерпретатор байт-кода / VM. ВМ / интерпретатор использует небольшую архитектуру CISC (операции могут различаться по размеру) с языком, указанным ниже. После завершения вы должны напечатать значение 3 регистров ЦП, чтобы доказать, что выводится правильный вывод (3 126 900 366).
составитель
Если вы хотите сделать свои собственные тесты, компилятор размещен ниже. Не стесняйтесь размещать свои тесты с вашим ответом.
"ВМ" Технические характеристики
Виртуальная машина имеет 3 32-битных целочисленных регистра без знака: R0, R1, R2. Они представлены в шестнадцатеричном виде как 0x00, 0x01 и 0x02.
Следующие операции должны поддерживаться:
Формат: [имя] [... операнды ...], [шестнадцатеричный код операции] [... операнды повторяются ...]
- LOAD [регистр] [4-байтовое значение], 0x00 [регистр] [4-байтовое значение]
- PUSH [регистр], 0x02 [регистр]
- POP [регистрация], 0x03 [регистрация]
- ADD [регистр, 1 байт] [регистр, 1 байт], 0x04 [регистр] [регистр]
- SUB [регистр, 1 байт] [регистр, 1 байт], 0x05 [регистр] [регистр]
- MUL [регистр, 1 байт] [регистр, 1 байт], 0x06 [регистр] [регистр]
- DIV [регистр, 1 байт] [регистр, 1 байт], 0x07 [регистр] [регистр]
- JMP [строка кода, 4 байта], 0x08 [номер строки кода 4 байта]
- CMP [регистр, 1 байт] [регистр, 1 байт], 0x09 [регистр] [регистр]
- BRANCHLT [строка кода, 4 байта], 0x0a [номер строки кода 4 байта]
Некоторые заметки:
- Вышеприведенные математические операции складывают значения двух регистров вместе, помещая вывод в первый регистр.
- CMP, оператор сравнения, должен сравнивать значения двух регистров и сохранять выходные данные в некотором внутреннем флаге (это может зависеть от реализации) для будущего использования в инструкциях ветвления.
- Если BRANCH вызывается до CMP, если не вызывается BRANCHEQ, «VM» не должна переходить.
- PUSH / POP неудивительно толкать или выталкивать числа из стека.
- Операторы Jump и Branch переходят к определенной операции (строке кода), а не к двоичному адресу.
- Операции ветвления не делают сравнения. Скорее, они берут вывод из последнего сравнения для выполнения.
- Операторы Branch и Jump используют систему индексации номеров строк, начинающуюся с нуля. (Например, JMP 0 переходит на первую строку)
- Все операции должны выполняться над числами без знака, которые переполняются до нуля и не генерируют исключение при переполнении целых чисел.
- Деление на ноль не допускается и, как таковое, поведение программы не определяется. Вы можете (например) ...
- Сбой программы.
- Завершите выполнение виртуальной машины и верните ее текущее состояние.
- Показать сообщение «ERR: Деление на 0».
- Завершение программы определяется как то, когда указатель инструкции достигает конца программы (можно предположить, что программа не пустая).
Выход Выходные данные должны быть именно такими (включая новые строки)
R0 3126900366
R1 0
R2 10000
Очки
Очки рассчитываются по следующей формуле:Number Of Characters * (Seconds Needed To Run / 2)
Чтобы избежать различий в оборудовании, приводящих к разному времени, каждый тест будет выполняться на моем компьютере (i5-4210u, 8 ГБ ОЗУ) на сервере Ubuntu или в Windows 8, поэтому старайтесь не использовать какое-то безумно-экзотическое время выполнения, которое компилируется только на Dual G5 Mac Pro с ровно 762,66 МБ свободной оперативной памяти.
Если вы используете специализированную среду выполнения / язык, пожалуйста, оставьте ссылку на нее.
- Для заинтересованных сторон я разместил тестовый код (написанный на C #) здесь: http://pastebin.com/WYCG5Uqu
Тестовая программа
Идея пришла отсюда , поэтому мы будем использовать несколько измененную версию их программы.
Правильный вывод для программы: 3 126 900 366
В С:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
В коде: [R0 является представителем s, R1 из j, R2 из i]
LOAD R0 0
LOAD R2 0 <--outer loop value
LOAD R1 0 <--inner loop value
--Begin inner loop--
PUSH R1 <--push inner loop value to the stack
MUL R1 R2 <--(i*j)
PUSH R2
LOAD R2 3
DIV R1 R2 <-- / 3
POP R2
ADD R0 R1 <-- s+=
POP R1
PUSH R2
LOAD R2 1
ADD R1 R2 <--j++
POP R2
PUSH R2
LOAD R2 10000
CMP R1 R2 <-- j < 10000
POP R2
BRANCHLT 3 <--Go back to beginning inner loop
--Drop To outer loop--
LOAD R1 1
ADD R2 R1 <--i++
LOAD R1 10000
CMP R2 R1 <-- i < 10000
LOAD R1 0 <--Reset inner loop
BRANCHLT 2
В двоичном / шестнадцатеричном виде:
0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x02 0x00 0x00 0x00 0x00
0x00 0x01 0x00 0x00 0x00 0x00
0x02 0x01
0x06 0x01 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x03
0x07 0x01 0x02
0x03 0x02
0x04 0x00 0x01
0x03 0x01
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x01
0x04 0x01 0x02
0x03 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x27 0x10
0x09 0x01 0x02
0x03 0x02
0x0a 0x00 0x00 0x00 0x03
0x00 0x01 0x00 0x00 0x00 0x01
0x04 0x02 0x01
0x00 0x01 0x00 0x00 0x27 0x10
0x09 0x02 0x01
0x00 0x01 0x00 0x00 0x00 0x00
0x0a 0x00 0x00 0x00 0x02
Бонусные баллы (эффекты применяются мультипликативно) Например, если вы подходите для всех трех, это будет ((символы * 0.50) * 0.75) * 0.90
- Уменьшение на 50%, если интерпретатор на самом деле является JIT-компилятором
- Уменьшение на 25%, если применяется какой-либо цикл развертывания / значимой оптимизации.
- Уменьшение на 10% при расширении виртуальной машины
- BRANCHEQ [строка кода, 4 байта] (ветвь, если равно - код операции 0x0b)
- BRANCHGT [строка кода, 4 байта] (ветвь, если больше - код операции 0x0c)
- BRANCHNE [строка кода, 4 байта] (ветвь, если не равно - код операции 0x0d)
- ЗАГРУЗИТЬ [регистр 1] [регистр 2] (переместить значение регистра 2 в регистр 1 - код операции 0x01).
Disallowed
- Прекомпиляция тестового примера в программу запрещена. Вы должны либо принять байт-код из STDIN или из файла (неважно, какой).
- Возврат вывода без запуска программы.
- Любой другой способ обмануть требование виртуальной машины.
CMP
Проверяет ли меньше или равенство? И что происходит с его результатом?
MUL
и DIV
также не указаны. Должны ли они быть подписаны или не подписаны? Что происходит при переполнении умножения?