Leaderboard - JIT Compiled (Weniger ist besser)
- es1024 - 81.2 Punkte (einschließlich eines funktionierenden Compilers!)
- Kieth Randall - 116 Punkte
- Ell - 121 Punkte
Bestenliste - Ausgelegt (Weniger ist besser)
- Martin Büttner - 706654 Punkte (ungefähr 2 Stunden).
- Kriptychon - 30379 Punkte (97 Sekunden)
Wenn Sie dies akzeptieren, besteht Ihre Aufgabe darin, den kleinstmöglichen Bytecode-Interpreter / VM zu schreiben. Der VM / Interpreter verwendet eine kleine CISC-Architektur (Operationen können unterschiedlich groß sein) mit der unten angegebenen Sprache. Nach Abschluss müssen Sie den Wert der 3 CPU-Register drucken, um zu beweisen, dass die richtige Ausgabe gedruckt wird (3.126.900.366).
Compiler
Wenn Sie Ihre eigenen Tests durchführen möchten, finden Sie unten einen Compiler. Fühlen Sie sich frei, Ihre Tests mit Ihrer Antwort zu posten.
"VM" Spezifikationen
Die VM hat 3 vorzeichenlose 32-Bit-Integralregister: R0, R1, R2. Sie werden hexadezimal als 0x00, 0x01 und 0x02 dargestellt.
Die folgenden Vorgänge müssen unterstützt werden:
Das Format ist [Name] [... Operanden ...], [hexadezimaler Op-Code] [... Operanden wiederholt ...]
- LOAD [Register] [4-Byte-Wert], 0x00 [Register] [4-Byte-Wert]
- PUSH [register], 0x02 [register]
- POP [register], 0x03 [register]
- ADD [Register, 1 Byte] [Register, 1 Byte], 0x04 [Register] [Register]
- SUB [Register, 1 Byte] [Register, 1 Byte], 0x05 [Register] [Register]
- MUL [Register, 1 Byte] [Register, 1 Byte], 0x06 [Register] [Register]
- DIV [Register, 1 Byte] [Register, 1 Byte], 0x07 [Register] [Register]
- JMP [Codezeile, 4 Byte], 0x08 [4 Byte Codezeilennummer]
- CMP [Register, 1 Byte] [Register, 1 Byte], 0x09 [Register] [Register]
- BRANCHLT [Codezeile, 4 Byte], 0x0a [4 Byte Codezeilennummer]
Einige Notizen:
- Die obigen mathematischen Operationen addieren die Werte von 2 Registern und platzieren die Ausgabe im ersten Register.
- CMP, der Vergleichsoperator, sollte die Werte von 2 Registern vergleichen und die Ausgabe in einem internen Flag (dies kann implementierungsspezifisch sein) für die zukünftige Verwendung in Verzweigungsanweisungen speichern.
- Wenn BRANCH vor CMP aufgerufen wird, sollte die "VM" nicht verzweigen, es sei denn, BRANCHEQ wird aufgerufen.
- PUSH / POP drücken oder knacken Zahlen aus dem Stapel.
- Sprung- und Verzweigungsoperatoren springen zu einer bestimmten Operation (Codezeile), nicht zu einer binären Adresse.
- Verzweigungsoperationen führen den Vergleich nicht durch. Sie nehmen vielmehr die Ausgabe des letzten Vergleichs zur Ausführung.
- Branch- und Jump-Operatoren verwenden ein auf Null basierendes Indizierungssystem für Zeilennummern. (ZB JMP 0 springt in die erste Zeile)
- Alle Operationen müssen an vorzeichenlosen Zahlen ausgeführt werden, die auf Null überlaufen und bei einem Ganzzahlüberlauf keine Ausnahme auslösen.
- Eine Division durch Null ist nicht zulässig und daher ist das Verhalten des Programms nicht definiert. Sie können (zum Beispiel) ...
- Programm zum Absturz bringen.
- Beenden Sie die Ausführung der VM und geben Sie den aktuellen Status zurück.
- Meldung "ERR: Division by 0" anzeigen.
- Die Beendigung des Programms ist definiert als wenn der Befehlszeiger das Programmende erreicht (ein nicht leeres Programm kann angenommen werden).
Ausgabe Die Ausgabe muss genau das sein (Zeilenumbrüche inklusive)
R0 3126900366
R1 0
R2 10000
Punkte
Punkte werden nach folgender Formel berechnet:Number Of Characters * (Seconds Needed To Run / 2)
Um zu vermeiden, dass Hardwareunterschiede zu unterschiedlichen Zeiten führen, wird jeder Test auf meinem Computer (i5-4210u, 8 GB RAM) auf einem Ubuntu-Server oder unter Windows 8 ausgeführt. Versuchen Sie daher, keine wahnsinnig exotische Laufzeit zu verwenden, die nur auf einem Dual G5 kompiliert wird Mac Pro mit genau 762,66 MB freiem RAM.
Wenn Sie eine spezielle Laufzeit / Sprache verwenden, senden Sie bitte einen Link zu dieser.
- Für Interessenten habe ich den Testcode (geschrieben in C #) hier veröffentlicht: http://pastebin.com/WYCG5Uqu
Testprogramm
Die Idee kam von hier , also werden wir eine etwas modifizierte Version ihres Programms verwenden.
Die korrekte Ausgabe für das Programm lautet: 3.126.900.366
In C:
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
Im Code: [R0 steht stellvertretend für s, R1 für j, R2 für 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
In binär / 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
Bonuspunkte (Effekte werden multipliziert angewendet) Wenn Sie sich beispielsweise für alle drei qualifizieren, sind dies ((Zeichen * 0,50) * 0,75) * 0,90
- Reduzierung um 50%, wenn der Interpreter tatsächlich ein JIT-Compiler ist
- Reduzierung um 25%, wenn eine Art Loop-Unrolling / sinnvolle Optimierung angewendet wird.
- 10% weniger, wenn Sie die VM mit erweitern
- BRANCHEQ [Codezeile, 4 Bytes] (Verzweigen, wenn gleich - Opcode 0x0b)
- BRANCHGT [Codezeile, 4 Bytes] (Branch, wenn größer als - opcode 0x0c)
- BRANCHNE [Codezeile, 4 Bytes] (Verzweigen, wenn nicht gleich - Opcode 0x0d)
- RLOAD [register 1] [register 2] (verschiebe den Wert von register 2 nach register 1 - opcode 0x01).
Nicht erlaubt
- Das Vorkompilieren des Testfalls in das Programm ist verboten. Sie müssen entweder den Bytecode von STDIN oder von einer Datei akzeptieren (spielt keine Rolle, welche).
- Die Ausgabe zurückgeben, ohne das Programm auszuführen.
- Eine andere Möglichkeit, die VM-Anforderung zu umgehen.
CMP
auf weniger als oder Gleichheit? Und was passiert mit dem Ergebnis?
MUL
und DIV
sind auch unterbestimmt. Sollten sie unterschrieben oder nicht unterschrieben sein? Was passiert beim Multiplikationsüberlauf?