WinAli-アセンブリ言語を理解するための仮想CPU


8

WinAliは、Windows用のモデルアセンブラです。実際のCPUをエミュレートし、アセンブリ言語の学習と理解を支援することを目的としています。

ドイツ語のウィキペディアの記事:http : //de.wikipedia.org/wiki/WinAli(現時点では英語の記事はありません)

生成された出力をテストする場合:Googleドライブへのリンク(プログラム自体はドイツ語ですが、ドイツ語を理解していなくても簡単に使用できます)

WinAliに関するいくつかの情報(データと構文)

データ型:

WinAliの唯一のデータ型は、実際にはSmallintまたはshortである2バイト長の「整数」です。したがって、正しい型を処理する必要はありません。これも分割時に丸められます。

変数と定数:

変数は、コマンドの後に次のように定義されます。

name DS F
  • nameは明らかに変数の名前です
  • DSは新しい変数のキーワードです
  • Fは変数の長さをビット単位で定義します。これはゼロベースで16進数なので、F = 16ビット

定数は非常に似ています:

name DC value
  • nameは単に定数の名前です
  • DCは新しい定数のキーワードです
  • valueは、その定数に割り当てられたです。two DC '2'
  • コードの最後に定数を指定する必要はありません。LDA(load)操作でインラインに書き込むこともできますLDA 0,'2'。これにより、「0」がレジスター0(アキュムレーター)にロードされます。
構文:

コードは、スペースまたはタブで区切られた4つの列に配置されます。

label command params comment
  • labelb labelコマンド(goto label)に使用され、しばしばスキップされます。
  • 以下にリストされているコマンドのいずれかをコマンドします。
  • params 1つまたは2つのパラメータと少なくとも1つのレジスタ、必要に応じて別のレジスタ、変数、スタック、またはアドレス。これらのパラメーターはコンマ(,)で区切られます。
  • コメント(オプション)行末までの、;または*行末までのコメント。

小さなコード参照:

コマンドは他にもありますが、この課題ではこれらのコマンドのみが必要です。

  • INI A 次のユーザー入力を変数に格納します A
  • OUTI A変数Aが保持している値を出力します。なんらかの理由で、ここではレジスターを使用できません。
  • LDA 0,Aの値Aをレジスタ0にロードします
  • STA 0,A レジスタ0の値を変数に格納します A
  • ADD 0,AAの値をレジスタ0 の値に追加します
  • SUB 0,AAの値にレジスタ0 の値を乗算します
  • DIV 0,AAの値をレジスタ0 の値で除算します
  • EOJジョブの終了、つまり実行可能コードを定義します。変数と定数の宣言はこのマークの後に始まります。

この課題には明示的に必要ありません:

  • program START 0実行する最初のアドレスを0、つまり次の行に設定します(これprogramはプログラムの名前ですが、コンパイラーに必要です)
  • END program プログラムを終了します。つまり、他の操作が続く場合でも実行を停止します

あなたの挑戦!

定数と変数を含む数式を受け取り、すべての変数を入力として受け取り、その式の結果を出力するWinAliコードを出力するプログラムまたはスクリプトを記述します。

  • STARTおよびENDコマンドを出力する必要はありません
  • WinAliには16個のレジスターが定義されていますが、すべての計算のアキュムレーターであるレジスター0のみを使用します。
  • コマンドのパラメーターとして2つの変数を使用することはできません。すべての結果をアキュムレータに保存する必要があります(レジスタ0)
  • 入力は常にどちらか、x:=(a+b)/cまたは単にの形式になります(a+b)/c、あなたが決める
  • あなただけの世話をする必要がある+ - * / (ADD, SUB, MUL, DIV)ので、根、平方、さらには洞のような複雑な計算はありません
  • ヒント:唯一の2つの引数は、例えばとの最初の抽出物の簡単な表現しようとしa:=a+b、その後x:=a/c
  • ヒント:コードで後で使用されない変数を上書きできない場合、プログラムは追加の(補助)変数を使用できます。それらをとして定義しますh1 DS F
  • ヒント:空の行は役に立ちません。それらを避けるようにしてください。(あなたは本当にそれらを必要としません)

例:

数式:
 x:=(a + b)* c

予想される出力(空の行は読みやすくするためです):
    INI a
    INI B
    INI C

    LDA 0、a
    0、bを追加
    MUL 0、c
    STA 0、a

    OUTI a
    EOJ
DS F
b DS F
c DS F

得点:

あなたのスコアは、あなたのコードの長さによって定義される+次の式の出力の長さ:

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

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

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

x:=2*a-b*c+d
  • コードで式の単項マイナスを処理できる場合は-10%

引き分けの場合、最も短い有効なWinAliコードを生成する答えが優先されます。

ソリューションは、いかなる方法でもハードコーディングされていない場合があります。私はあなたの答えが正しいことを確認するために追加の表現で各答えを検証します。


数式とは正確には何ですか?たとえば、負の定数は許可されますか?単項マイナス?変数名が1文字より長いですか?
nutki 2014年

入力ディレクティブ(INI x)は特定の順序に従う必要がありますか?
nutki 2014年

@nutki数式は単純なx = a + bのようなものなので、複雑な方程式を解くことはできません。負の定数は許可されます。変数名は複数の文字にすることができます(abはa * bではありません)。INIxは次の場所に配置できます次の入力を
Give

@nutki単項マイナスとは、次のような意味MUL 0,-aですか?負のアドレスがないため(これaは値へのポインターにすぎません)、これは不可能ですが、0から値を減算して負の表現(SUB 0,a)を取得し、この負の値を処理できます。これを元の変数に格納することもできます。
GiantTree 2014年

入力式で単項マイナスを意味したので、たとえばx:=-a*bまたはx:=a/-(b+c)。入力順序が指定されていないので、WinAliコードで同じ変数名を使用する必要があると思いますが、そうですか?これらの制限により、入力に決してない識別子はありますか?たとえばh1、入力変数名にすることができますか?
nutki 2014年

回答:


4

Perl 5:948、355コード+ 593出力

ゴルフの後。以前の短いバージョンは正しく解析されませんでした(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

使用例:

$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

確認済み。入力がアルファベット順にソートされていると便利です。ヒントは1つです。空の行は無視されるため、出力の長さが少し短くなる可能性があります
GiantTree

実行できるいくつかの最適化:末尾の新しい行を削除
GiantTree

上記の最適化により、出力は585バイト(8バイト少ない)になります
GiantTree

末尾の改行はコードコストなしで削除できますが、INIの後に空行を削除するには、おそらく4文字を超えるコードが必要になります。
nutki 2014年

ああ、それから最後の改行を削除するだけです。これは必要ありません。4バイト節約できます:)
GiantTree
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.