WinAli - Virtuelle CPU zum Verständnis der Assemblersprache

8

WinAli ist ein Model Assembler für Windows. Es emuliert eine echte CPU und soll den Schülern helfen, die Assemblersprache zu lernen und zu verstehen.

Deutscher Wikipedia-Artikel: http://de.wikipedia.org/wiki/WinAli (derzeit gibt es keinen englischen Artikel)

Falls Sie Ihre produzierte Ausgabe testen möchten: Link zu Google Drive (das Programm selbst ist auf Deutsch, aber einfach zu bedienen, auch wenn Sie kein Deutsch verstehen)

Einige Informationen zu WinAli (Daten und Syntax)

Datentypen:

Der einzige Datentyp in WinAli ist eine 2 Byte lange "Ganzzahl", bei der es sich tatsächlich um eine Smallint oder Short handelt . Sie müssen sich also nicht um die richtigen Typen kümmern. Dies wird auch beim Teilen gerundet.

Variablen und Konstanten:

Variablen werden nach den Befehlen folgendermaßen definiert:

name DS F
  • Name ist offensichtlich der Name der Variablen
  • DS ist das Schlüsselwort für eine neue Variable
  • F definiert die Länge der Variablen in Bits; Dies ist nullbasiert und hexadezimal, also F = 16 Bit

Konstanten sind sehr ähnlich:

name DC value
  • name ist einfach der Name der Konstante
  • DC ist das Schlüsselwort für eine neue Konstante
  • value ist der dieser Konstante zugewiesene Wert, ztwo DC '2'
  • Sie müssen keine Konstanten am Ende des Codes angeben. Sie können sie auch inline mit der LDA(Lade-) Operation schreiben, z LDA 0,'2'. Dies lädt "2" in Register 0 (den Akkumulator).
Syntax:

Der Code ist in 4 Spalten ausgerichtet, die durch ein Leerzeichen oder eine Registerkarte getrennt sind:

label command params comment
  • label wird für den b labelBefehl ( goto label) verwendet und häufig übersprungen.
  • Befehl einer der unten aufgeführten Befehle.
  • params ein oder zwei Parameter mit mindestens einem Register und bei Bedarf einem anderen Register, einer Variablen, einem Stapel oder einer Adresse; Diese Parameter werden durch ein Komma ( ,) getrennt.
  • Kommentare (optional) Ein Kommentar, dem ;oder *bis zum Ende der Zeile vorangestellt ist .

Kleine Code-Referenz:

Es gibt mehr Befehle, aber für diese Herausforderung benötigen Sie nur folgende:

  • INI A Speichert die nächste Benutzereingabe in einer Variablen A
  • OUTI AGibt den Wert aus, den die Variable Ahält. Sie können hier aus irgendeinem Grund kein Register verwenden.
  • LDA 0,ALädt den Wert von Ain Register 0
  • STA 0,A Speichert den Wert von Register 0 in der Variablen A
  • ADD 0,AAddiert den Wert von Azum Wert von Register 0
  • SUB 0,AMultipliziert den Wert von Amit dem Wert von Register 0
  • DIV 0,ADividiert den Wert von Adurch den Wert von Register 0
  • EOJDefiniert das Ende des Jobs, dh ausführbaren Code. Variable und konstante Deklarationen beginnen nach dieser Marke.

Nicht explizit für diese Herausforderung erforderlich:

  • program START 0Setzt die erste auszuführende Adresse auf 0, dh die nächste Zeile ( programist nur der Name des Programms, wird aber für den Compiler benötigt).
  • END program Beendet das Programm, dh beendet die Ausführung, selbst wenn andere Vorgänge folgen würden

Ihre Herausforderung!

Schreiben Sie ein Programm oder Skript, das einen mathematischen Ausdruck mit konstanten Zahlen und Variablen verwendet und den WinAli-Code ausgibt, der alle Variablen als Eingabe verwendet und das Ergebnis dieses Ausdrucks ausgibt.

  • Sie müssen die Befehle STARTund nicht ausgebenEND
  • Obwohl in WinAli 16 Register definiert sind, verwenden wir nur das Register 0, das der Akkumulator für alle Berechnungen ist
  • Sie können nicht zwei Variablen als Parameter eines Befehls verwenden. Sie müssen alle Ihre Ergebnisse im Akkumulator speichern (Register 0)
  • Die Eingabe erfolgt immer entweder x:=(a+b)/coder einfach (a+b)/c, Sie entscheiden
  • Sie müssen sich nur darum kümmern + - * / (ADD, SUB, MUL, DIV), also keine komplexen Berechnungen wie Wurzeln, Quadrate oder gar Sinus
  • Tipp: Versuchen Sie , erste Extrakt einfache Ausdrücke mit nur zwei Argumente , zB a:=a+bdannx:=a/c
  • Tipp: Ihr Programm darf zusätzliche (Hilfs-) Variablen verwenden, wenn Sie keine Variablen überschreiben können, die später in Ihrem Code nicht verwendet werden. Definieren Sie sie als h1 DS F.
  • Tipp: Leere Zeilen sind nutzlos. Versuche sie zu vermeiden. (Du brauchst sie wirklich nicht)

Beispiel:

Mathematischer Ausdruck:
 x: = (a + b) * c

Erwartete Ausgabe (leere Zeilen erleichtern das Lesen):
    INI a
    INI b
    INI c

    LDA 0, a
    ADD 0, b
    MUL 0, c
    STA 0, a

    OUTI a
    EOJ
ein DS F.
b DS F.
c DS F.

Wertung:

Ihre Punktzahl wird durch die Länge Ihres Codes + die Länge der Ausgabe der folgenden Ausdrücke definiert:

x:=a+b+c*c/d

x:=(a+b)/c-d

x:=a-b*c-d/e

x:=2*a-b*c+d
  • -10%, wenn Ihr Code unäre Minuszeichen in Ausdrücken verarbeiten kann.

Im Falle eines Unentschieden gewinnt die Antwort, die den kürzesten funktionierenden WinAli-Code erzeugt.

Die Lösungen dürfen in keiner Weise fest codiert werden. Ich werde jede Antwort mit zusätzlichen Ausdrücken validieren, um sicherzustellen, dass Ihre Antwort korrekt ist.

GiantTree
quelle
Was genau ist ein mathematischer Ausdruck? Sind zum Beispiel negative Konstanten erlaubt? Unäres Minus? Variablennamen länger als ein Buchstabe?
Nutki
Müssen die Eingabeanweisungen (INI x) einer bestimmten Reihenfolge folgen?
Nutki
@nutki ein mathematischer Ausdruck ist wie ein einfaches x = a + b gemeint, so dass keine Lösung komplexer Gleichungen möglich ist, negative Konstanten zulässig sind, Variablennamen aus mehr als einem Buchstaben bestehen können (ab ist nicht a * b), INI x kann wo gesetzt werden Wie auch immer Sie möchten, es ist keine bestimmte Reihenfolge erforderlich, da die nächste Eingabe in der Give-Variablen
gespeichert wird.
@nutki von unary minus du meinst Dinge wie MUL 0,-a? Dies ist nicht möglich, da keine negativen Adressen vorhanden sind (dies aist nur ein Zeiger auf einen Wert). Sie können jedoch den Wert von 0 subtrahieren, um die negative Darstellung ( SUB 0,a) zu erhalten, und dann mit diesem negativen Wert arbeiten. Möglicherweise können Sie dies sogar in der ursprünglichen Variablen speichern.
GiantTree
Ich meinte unäres Minus im Eingabeausdruck, zum Beispiel x:=-a*boder x:=a/-(b+c). Da die Eingabereihenfolge nicht angegeben ist, müssen wir vermutlich die gleichen Variablennamen im WinAli-Code verwenden. Ist das der Fall? Gibt es mit diesen Einschränkungen Bezeichner, die niemals in der Eingabe enthalten sind? Kann zum Beispiel h1ein Eingabevariablenname sein?
Nutki

Antworten:

4

Perl 5: 948, 355 Code + 593 Ausgabe

Nach einigem Golfen. Die vorherige kürzere Version wurde nicht richtig analysiert (a+b)-4*c.

%m=split'\b','-SUB+ADD/DIV*MUL<LDA>STA';$i='(\w+|(?<!\w|\))-\d+)';
$_=<>;@x{@y=/([a-z]\w*)/gi}=@y;print"\tINI $_
"for@x=keys%x;
$f=$_,$x.="<$&>".($g=(grep$f!~$_,a..zz)[0]),$x{$g}=s/@/$g/
while s|\($i\)|$1|g,s|$i[*/]$i|@|||s|$i[+-]$i|@|;$_="$x
\tOUTI $_\tEOJ
";s/>$i<\1//g;s!(^|\b)[-+/*<>]!\n\t$m{$&} 0,!g;
s!-?\d+$!'$&'!mg;print;print"$_\tDS F
"for keys%x

Anwendungsbeispiel:

$perl winali.pl <<<"2*a-b*c+d"
    INI b
    INI a
    INI d
    INI c

    LDA 0,'2'
    MUL 0,a
    STA 0,a
    LDA 0,b
    MUL 0,c
    STA 0,b
    LDA 0,a
    SUB 0,b
    ADD 0,d
    STA 0,b
    OUTI b
    EOJ
b   DS F
a   DS F
d   DS F
c   DS F
Nutki
quelle
Verifiziert. Wäre schön wenn die Eingabe alphabetisch sortiert wäre. Nur ein Tipp: Leere Zeilen werden ignoriert, sodass sie Ihre Ausgabelänge ein wenig reduzieren können
GiantTree
Einige Optimierungen, die Sie
vornehmen
Mit den oben genannten Optimierungen wird Ihre Ausgabe 585 Bytes lang (8 Bytes weniger) sein
GiantTree
Nachfolgende Zeilenumbrüche können ohne Codekosten entfernt werden. Das Entfernen einer leeren Zeile nach INI würde jedoch wahrscheinlich mehr als 4 Codezeichen kosten.
Nutki
Oh, dann entferne einfach die nachfolgende Newline, sie wird nicht benötigt und spart dir 4 Bytes :)
GiantTree