Табло - Складено JIT (нижче краще)
- es1024 - 81,2 бала (включаючи робочий компілятор!)
- Кіт Рендалл - 116 балів
- Елл - 121 бал
Таблиця лідерів - Інтерпретована (нижче краще)
- Мартін Бюттнер - 706654 балів (десь близько 2 годин).
- криптих - 30379 балів (97 секунд)
Якщо ви вирішите прийняти це, ваша місія полягає в тому, щоб написати найменший можливий інтерпретатор байт-коду / VM. ВМ / інтерпретатор використовує невелику архітектуру CISC (операції можуть відрізнятися за розміром), мовою, зазначеною нижче. Після завершення потрібно надрукувати значення трьох регістрів процесора, щоб довести, що надруковано правильний вихід (3,126,900,366).
Укладач
Якщо ви хочете зробити власні тести, нижче розміщений компілятор. Сміливо розміщуйте свої тести зі своєю відповіддю.
Технічні характеристики "VM"
ВМ має 3 32-бітні непідписані інтегральні регістри: R0, R1, R2. Вони представлені в шістнадцятковій формі як 0x00, 0x01 та 0x02.
Необхідно підтримувати наступні операції:
Формат: [ім'я] [... операнди ...], [шістнадцятковий оп-код] [... операнди повторюються ...]
- ЗАВАНТАЖЕННЯ [регістр] [4 байтне значення], 0х00 [регістр] [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, оператор порівняння, повинен порівнювати значення 2 регістрів і зберігати вихід у якомусь внутрішньому прапорі (це може бути специфічно для реалізації) для подальшого використання в інструкціях гілки.
- Якщо BRANCH викликається перед CMP, якщо BRANCHEQ не викликається, "VM" не повинен розгалужуватися.
- PUSH / POP несподівано натискає чи виводить номери зі стека.
- Оператори Jump and Branch переходять до певної операції (рядка коду), а не бінарної адреси.
- Операції з філіями не роблять порівняння. Швидше, вони беруть висновок з останнього порівняння для виконання.
- Оператори відділення та переходу використовують систему індексації нумерації рядків на основі нуля. (Наприклад, JMP 0 переходить до першого рядка)
- Усі операції слід виконувати на непідписаних числах, які переповнюються до нуля і не викидають виняток для цілого переповнення.
- Ділення на нуль заборонено, і поведінка програми не визначається. Ви можете (наприклад) ...
- Збій програму.
- Закінчити виконання VM та повернути його поточний стан.
- Показати повідомлення "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% зменшується, якщо ви продовжите VM за допомогою
- BRANCHEQ [рядок коду, 4 байти] (Відгалуження, якщо рівне - опкод 0x0b)
- BRANCHGT [рядок коду, 4 байти] (Відділення, якщо більше - opcode 0x0c)
- BRANCHNE [рядок коду, 4 байти] (Відгалуження, якщо не рівне - opcode 0x0d)
- RLOAD [регістр 1] [регістр 2] (перемістіть значення регістру 2 на реєстр 1 - опкод 0x01).
Заборонено
- Попереднє компілювання тестового випадку в програму заборонено. Ви повинні або прийняти байт-код із STDIN або з файлу (не важливо, який).
- Повернення виводу без запуску програми.
- Будь-який інший спосіб ви можете придумати, щоб обдурити вимогу VM.
CMP
перевіряється на менше чи рівність? І що відбувається з її результатом?
MUL
і DIV
також не визначено. Чи повинні вони бути підписані або без підпису? Що відбувається при переповненні множення?