WinAli - Virtual CPU untuk memahami bahasa assembly

8

WinAli adalah assembler model untuk Windows. Ini mengemulasi CPU nyata dan dimaksudkan untuk membantu siswa belajar dan memahami bahasa Assembly.

Artikel Wikipedia bahasa Jerman: http://de.wikipedia.org/wiki/WinAli (saat ini tidak ada artikel bahasa Inggris)

Jika Anda ingin menguji output yang dihasilkan: Tautan ke Google Drive (program itu sendiri dalam bahasa Jerman tetapi mudah digunakan bahkan jika Anda tidak mengerti bahasa Jerman)

Beberapa informasi tentang WinAli (data dan sintaksis)

Tipe data:

Satu-satunya tipe data di WinAli adalah "Integer" 2 byte panjang yang sebenarnya merupakan Smallint atau pendek . Jadi Anda tidak perlu merawat tipe yang benar. Ini juga bulat saat membelah.

Variabel dan konstanta:

Variabel didefinisikan seperti ini setelah perintah:

name DS F
  • nama jelas nama variabel
  • DS adalah kata kunci untuk variabel baru
  • F mendefinisikan panjang variabel dalam bit; ini berbasis nol dan heksadesimal sehingga F = 16 bit

Konstanta sangat mirip:

name DC value
  • nama hanyalah nama konstanta
  • DC adalah kata kunci untuk konstanta baru
  • nilai adalah nilai yang ditetapkan untuk konstanta itu misalnyatwo DC '2'
  • Anda tidak perlu menentukan konstanta di akhir kode. Anda juga dapat menuliskannya sesuai dengan operasi LDA(memuat) mis LDA 0,'2'. Ini memuat "2" ke register 0 (akumulator).
Sintaksis:

Kode disejajarkan menjadi 4 kolom yang dipisahkan oleh spasi atau tab:

label command params comment
  • label digunakan untuk b labelperintah ( goto label) dan sering dilewati.
  • perintah salah satu perintah yang tercantum di bawah ini.
  • params satu atau dua parameter dengan setidaknya satu register dan jika perlu register lain, variabel, stack atau alamat; parameter ini dipisahkan oleh koma ( ,).
  • komentar (opsional) komentar yang diawali dengan ;atau *sampai akhir baris.

Referensi kode kecil:

Ada lebih banyak perintah tetapi untuk tantangan ini Anda hanya perlu itu:

  • INI A Menyimpan input pengguna berikutnya ke dalam variabel A
  • OUTI AMenghasilkan nilai yang Adipegang variabel . Anda tidak dapat menggunakan register di sini karena alasan tertentu.
  • LDA 0,AMemuat nilai Ake register 0
  • STA 0,A Menyimpan nilai register 0 ke dalam variabel A
  • ADD 0,AMenambahkan nilai Ake nilai register 0
  • SUB 0,AMengalikan nilai Adengan nilai register 0
  • DIV 0,AMembagi nilai Adengan nilai register 0
  • EOJMenentukan akhir pekerjaan, yaitu kode yang dapat dieksekusi. Deklarasi variabel dan konstan dimulai setelah tanda ini.

Tidak secara eksplisit diperlukan untuk tantangan ini:

  • program START 0Menetapkan alamat pertama yang akan dieksekusi ke 0 yaitu baris berikutnya ( programhanya nama program tetapi diperlukan untuk kompiler)
  • END program Berakhir program yaitu berhenti mengeksekusi, bahkan jika operasi lain akan mengikuti

Tantangan anda!

Tulis program atau skrip yang mengambil ekspresi matematis dengan angka dan variabel konstan dan mengeluarkan kode WinAli yang mengambil semua variabel sebagai input dan output hasil ekspresi itu.

  • Anda tidak perlu menampilkan STARTdan ENDmemerintahkan
  • Meskipun ada 16 register yang didefinisikan dalam WinAli kami hanya menggunakan register 0, yang merupakan akumulator untuk semua perhitungan
  • Anda tidak dapat menggunakan dua variabel sebagai parameter perintah. Anda harus menyimpan semua hasil Anda ke dalam akumulator (daftar 0)
  • Masukan selalu dalam bentuk salah satu x:=(a+b)/catau hanya (a+b)/c, Anda memutuskan
  • Anda hanya perlu dirawat + - * / (ADD, SUB, MUL, DIV), jadi tidak ada perhitungan rumit seperti akar, kuadrat atau bahkan sinus
  • Tip: Cobalah untuk ekspresi ekstrak sederhana pertama dengan hanya 2 argumen misalnya a:=a+bmakax:=a/c
  • Kiat: Program Anda diizinkan untuk menggunakan variabel tambahan (tambahan) jika Anda tidak dapat menimpa variabel yang tidak digunakan nanti dalam kode Anda. Tentukan mereka sebagai h1 DS F.
  • Kiat: Baris kosong tidak berguna. Cobalah untuk menghindarinya. (Anda benar-benar tidak membutuhkannya)

Contoh:

Ekspresi matematika:
 x: = (a + b) * c

Output yang diharapkan (baris kosong lebih mudah dibaca):
    INI a
    INI b
    INI c

    LDA 0, a
    TAMBAH 0, b
    MULUS 0, c
    STA 0, a

    OUTI a
    EOJ
a DS F
b DS F
c DS F

Mencetak:

Skor Anda ditentukan oleh panjang kode Anda + panjang output dari ekspresi berikut:

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

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

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

x:=2*a-b*c+d
  • -10% jika kode Anda dapat menangani minus unary dalam ekspresi.

Dalam kasus seri, jawaban yang menghasilkan kode WinAli terpendek akan menang.

Solusi mungkin tidak dapat dikodekan dengan cara apa pun. Saya akan memvalidasi setiap jawaban dengan ekspresi tambahan untuk memastikan jawaban Anda benar.

GiantTree
sumber
Apa sebenarnya ungkapan matematika itu? Misalnya apakah konstanta negatif diperbolehkan? Minus unary? Nama variabel lebih dari satu huruf?
nutki
Apakah arahan input (INI x) perlu mengikuti urutan tertentu?
nutki
@nutki ekspresi matematis dimaksudkan seperti x = a + b yang sederhana sehingga tidak ada penyelesaian persamaan kompleks, konstanta negatif diperbolehkan, nama variabel dapat lebih dari satu huruf (ab bukan a * b), INI x dapat diletakkan di tempat pernah Anda suka tidak ada pesanan khusus yang diperlukan karena ia menyimpan input berikutnya ke dalam variabel give tetapi akan lebih baik jika mereka mengikuti perintah az alih-alih acak
GiantTree
@nutki oleh unary minus maksudmu hal-hal seperti MUL 0,-a? ini tidak mungkin karena tidak ada alamat negatif ( ahanya pointer ke nilai), tetapi Anda dapat mengurangi nilai dari 0 untuk mendapatkan representasi negatif ( SUB 0,a) dan kemudian bekerja dengan nilai negatif ini; Anda bahkan dapat menyimpan ini dalam variabel asli.
GiantTree
Maksud saya minus unary dalam ekspresi input jadi misalnya x:=-a*batau x:=a/-(b+c). Karena urutan input tidak ditentukan, saya kira kita harus menggunakan nama variabel yang sama dalam kode WinAli, apakah itu masalahnya? Dengan pembatasan itu, adakah pengidentifikasi yang tidak pernah masuk? Misalnya dapat h1berupa nama variabel input?
nutki

Jawaban:

4

Perl 5: 948, kode 355 + output 593

Setelah bermain golf. Versi sebelumnya yang lebih singkat tidak diurai dengan benar (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

Contoh penggunaan:

$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
sumber
Diverifikasi. Alangkah baiknya jika input diurutkan berdasarkan abjad. Hanya satu tip: baris kosong diabaikan sehingga dapat mengurangi panjang output Anda sedikit
GiantTree
Beberapa optimasi yang dapat Anda lakukan: hapus baris baru yang tertinggal
GiantTree
Dengan optimasi di atas, output Anda akan menjadi 585 byte (kurang 8 byte)
GiantTree
Mengejar baris baru dapat dihapus tanpa biaya kode, tetapi untuk menghapus baris kosong setelah INI mungkin akan dikenakan biaya lebih dari 4 karakter kode.
nutki
oh, maka cukup hapus baris baru, itu tidak diperlukan dan akan menyelamatkan Anda 4 byte :)
GiantTree