Leaderboard - JIT Compiled (Lower is better)
- es1024 - 81,2 points (y compris un compilateur fonctionnel!)
- Kieth Randall - 116 points
- Ell - 121 points
Classement - Interprété (plus c'est bas, mieux c'est)
- Martin Büttner - 706654 points (environ 2 heures).
- manuscrit - 30379 points (97 secondes)
Votre mission, si vous l'acceptez, est d'écrire le plus petit interprète / VM de bytecode possible. La VM / interprète utilise une petite architecture CISC (les opérations peuvent varier en taille), avec la langue spécifiée ci-dessous. Une fois terminé, vous devez imprimer la valeur des 3 registres CPU pour prouver que la sortie correcte est imprimée (3 126 900 366).
Compilateur
Si vous souhaitez faire vos propres tests, un compilateur est affiché ci-dessous. N'hésitez pas à poster vos tests avec votre réponse.
Spécifications "VM"
La VM a 3 registres intégraux non signés 32 bits: R0, R1, R2. Ils sont représentés en hexadécimal comme 0x00, 0x01 et 0x02.
Les opérations suivantes doivent être prises en charge:
Le format est [nom] [... opérandes ...], [code op hexadécimal] [... opérandes répétés ...]
- LOAD [registre] [valeur 4 octets], 0x00 [registre] [valeur 4 octets]
- PUSH [registre], 0x02 [registre]
- POP [registre], 0x03 [registre]
- ADD [registre, 1 octet] [registre, 1 octet], 0x04 [registre] [registre]
- SUB [registre, 1 octet] [registre, 1 octet], 0x05 [registre] [registre]
- MUL [registre, 1 octet] [registre, 1 octet], 0x06 [registre] [registre]
- DIV [registre, 1 octet] [registre, 1 octet], 0x07 [registre] [registre]
- JMP [ligne de code, 4 octets], 0x08 [numéro de ligne de code de 4 octets]
- CMP [registre, 1 octet] [registre, 1 octet], 0x09 [registre] [registre]
- BRANCHLT [ligne de code, 4 octets], 0x0a [numéro de ligne de code 4 octets]
Quelques notes:
- Les opérations mathématiques ci-dessus additionnent les valeurs de 2 registres ensemble, plaçant la sortie dans le premier registre.
- CMP, l'opérateur de comparaison, doit comparer les valeurs de 2 registres et stocker la sortie dans un indicateur interne (cela peut être spécifique à l'implémentation) pour une utilisation future sur les instructions de branchement.
- Si BRANCH est appelé avant CMP, sauf si BRANCHEQ est appelé, la «VM» ne doit pas se ramifier.
- PUSH / POP sans surprise, push ou pop numéros de la pile.
- Les opérateurs de saut et de branche passent à une opération spécifique (ligne de code), et non à une adresse binaire.
- Les opérations des succursales ne font pas la comparaison. Au lieu de cela, ils prennent la sortie de la dernière comparaison pour s'exécuter.
- Les opérateurs de branche et de saut utilisent un système d'indexation de numéro de ligne basé sur zéro. (Par exemple, JMP 0 saute à la première ligne)
- Toutes les opérations doivent être effectuées sur des nombres non signés qui débordent à zéro et ne lèvent pas d'exception sur un dépassement d'entier.
- La division par zéro n'est pas autorisée et en tant que tel, le comportement du programme n'est pas défini. Vous pouvez (par exemple) ...
- Arrêtez le programme.
- Arrêtez l'exécution de la machine virtuelle et retournez son état actuel.
- Afficher un message "ERR: Division by 0".
- La fin du programme est définie comme lorsque le pointeur d'instruction atteint la fin du programme (un programme non vide peut être supposé).
Sortie La sortie doit être exactement celle-ci (nouvelles lignes incluses)
R0 3126900366
R1 0
R2 10000
Points Les
points sont calculés selon la formule suivante:Number Of Characters * (Seconds Needed To Run / 2)
Pour éviter les différences matérielles provoquant des heures différentes, chaque test sera exécuté sur mon ordinateur (i5-4210u, 8 Go de RAM) dans le serveur Ubuntu ou Windows 8, alors essayez de ne pas utiliser un runtime fou-exotique qui ne se compile que sur un Dual G5 Mac Pro avec exactement 762,66 Mo de RAM libre.
Si vous utilisez un runtime / langage spécialisé, veuillez poster un lien vers celui-ci.
- Pour les parties intéressées, j'ai publié le code de test (écrit en C #) ici: http://pastebin.com/WYCG5Uqu
Programme de test
L'idée est venue d' ici , nous allons donc utiliser une version quelque peu modifiée de leur programme.
La sortie correcte pour le programme est: 3 126 900 366
En C:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
Dans le code: [R0 est représentatif de s, R1 de j, R2 de 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
En binaire / hex:
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
Points bonus (les effets sont appliqués de manière multiplicative) Par exemple, si vous vous qualifiez pour les trois, ce serait ((caractères * 0,50) * 0,75) * 0,90
- Baisse de 50% si l'interpréteur est en fait un compilateur JIT
- 25% de diminution si elle applique une quelconque sorte de déroulement de boucle / optimisation significative.
- 10% de diminution si vous étendez la machine virtuelle avec
- BRANCHEQ [ligne de code, 4 octets] (Branche si égale - opcode 0x0b)
- BRANCHGT [ligne de code, 4 octets] (Branche si supérieure à - opcode 0x0c)
- BRANCHNE [ligne de code, 4 octets] (Branche si différente - opcode 0x0d)
- RLOAD [registre 1] [registre 2] (déplacez la valeur du registre 2 vers le registre 1 - opcode 0x01).
Rejeté
- La précompilation du cas de test dans le programme est interdite. Vous devez accepter le bytecode de STDIN ou d'un fichier (peu importe lequel).
- Renvoyer la sortie sans exécuter le programme.
- De toute autre manière à laquelle vous pouvez penser pour tromper l'exigence VM.
CMP
Vérifie- t-il moins que ou l'égalité? Et qu'advient-il de son résultat?
MUL
et DIV
sont également sous-spécifiés. Doivent-ils être signés ou non signés? Que se passe-t-il en cas de débordement de multiplication?