Catatan: Beberapa jawaban telah tiba. Pertimbangkan untuk membatalkan jawaban yang lebih baru juga.
- Gangguan umum dari happy5214
- C dari luser droog
- Java dari NeatMonster
- Javascript dari crempp
- C dari Mike C
- C ++ dari Darius Goad
- Catatan tambahan dari luser droog
- C ++ dari JoeFish
- Javascript dari sepenuhnya subyektif
- C dari RichTX
- C ++ dari Dave C
- Haskell dari JB
- Python dari ja
The 8086 adalah Intel mikroprosesor x86 pertama. Tugas Anda adalah menulis emulator untuk itu. Karena ini relatif maju, saya ingin membatasinya:
- Hanya opcode berikut yang perlu diimplementasikan:
- mov, push, pop, xchg
- tambahkan, adc, sub, sbb, cmp, dan, atau, xor
- inc, dec
- panggilan, ret, jmp
- jb, jz, jbe, js, jnb, jnz, jnbe, jns
- stc, clc
- hlt, tidak
- Sebagai akibatnya, Anda hanya perlu menghitung flag carry, zero, dan sign
- Jangan menerapkan segmen. Asumsikan
cs = ds = ss = 0
. - Tidak ada awalan
- Tidak ada jenis interupsi atau port IO
- Tidak ada fungsi string
- Tidak ada opcode dua byte (0F ..)
- Tidak ada aritmatika floating point
- (Jelas) tidak ada hal 32-bit, sse, mmx, ... apa pun yang belum ditemukan pada tahun 1979
- Anda tidak perlu menghitung siklus atau melakukan pengaturan waktu apa pun
Mulai dengan ip = 0
dan sp = 100h
.
Input: Emulator Anda harus mengambil program biner dalam format apa pun yang Anda suka sebagai input (baca dari file, array yang telah ditentukan, ...) dan muat ke dalam memori di alamat 0.
Output: RAM video dimulai pada alamat 8000h, setiap byte adalah satu (ASCII-) karakter. Emulasi layar 80x25 ke konsol. Perlakukan nol byte seperti spasi.
Contoh:
08000 2E 2E 2E 2E 2E 2E 2E 2E 2E 00 00 00 00 00 00 00 ................
08010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
08020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
08030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
08040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
08050 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 00 00 Hello,.world!...
Catatan: Ini sangat mirip dengan mode video nyata, yang biasanya pada 0xB8000 dan memiliki byte per karakter untuk warna.
Kriteria menang:
- Semua instruksi yang disebutkan perlu diimplementasikan
Saya membuat program uji uncommented ( tautan , sumber nasm ) yang harus berjalan dengan baik. Ini menghasilkan
......... Hello, world! 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ################################################################################ ## ## ## 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ## ## ## ## 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400 ## ## ## ## 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ################################################################################
Saya tidak yakin apakah ini seharusnya codegolf; ini semacam tugas yang sulit, jadi pengajuan apa pun akan memenangkan banyak upvotes. Tolong beri komentar anda.
Berikut ini beberapa tautan untuk membantu Anda dalam tugas ini:
- format instruksi , lebih lanjut
- tabel opcode
- deskripsi opcode
- 16-bit mod R / M byte decoding
- register , flag register
- Manual 1979
Ini adalah entri pertama saya ke platform ini. Jika ada kesalahan, harap tunjukkan; jika saya melewatkan detail, tanyakan saja.
sumber
Jawaban:
Jangan ragu untuk garpu dan golf: https://github.com/julienaubert/py8086
Saya juga menyertakan debugger interaktif.
Ada tiga file: emu8086.py (wajib) console.py (opsional untuk output display), disasm.py (opsional, untuk mendapatkan daftar asm dalam codegolf).
Untuk menjalankan dengan tampilan (catatan menggunakan kutukan):
Untuk dijalankan dengan debugger interaktif:
Untuk dijalankan dengan "debugger" non-interaktif:
Program " codegolf " harus berada di direktori yang sama.
emu8086.py
console.py
disasm.py
Di github
sumber
Haskell,
256234196 barisSaya sudah punya pekerjaan dalam proses ini untuk beberapa waktu, saya berniat untuk memolesnya sedikit lebih sedikit sebelum penerbitan, tetapi sekarang kesenangan itu secara resmi dimulai, tidak ada gunanya merahasiakannya lagi. Saya perhatikan ketika mengekstraksi bahwa panjangnya persis 256 baris, jadi saya kira itu berada pada titik "luar biasa" dari keberadaannya.
Apa yang ada di: hampir tidak cukup dari instruksi 8086 yang diatur untuk menjalankan contoh biner dengan sempurna. Kode modifikasi diri didukung. (prefetch: zero bytes)
Ironisnya, iterasi cukup pertama dari kode lebih panjang dan kurang didukung rentang opcode. Refactoring akhirnya bermanfaat baik untuk panjang kode dan cakupan opcode.
Apa yang keluar: jelas, segmen, awalan, dan opcode multibyte, interupsi, port I / O, operasi string, dan FP. Awalnya saya memang mengikuti
PUSH SP
perilaku asli , tetapi harus menghentikannya setelah beberapa kali pengulangan.Hasil flag carry mungkin sangat kacau dalam beberapa kasus
ADC
/SBB
.Bagaimanapun, ini kodenya:
Output untuk biner sampel yang disediakan cocok dengan spesifikasi dengan sempurna. Cobalah menggunakan doa seperti:
Sebagian besar operasi yang tidak diimplementasikan hanya akan menghasilkan kegagalan pencocokan pola.
Saya masih berniat memberi faktor lebih banyak, dan menerapkan output langsung aktual dengan kutukan.
Pembaruan 1: turun ke 234 baris. Lebih baik mengatur kode berdasarkan fungsionalitas, menyelaraskan apa yang bisa, mencoba menempel 80 kolom. Dan refactored ALU beberapa kali.
Pembaruan 2: sudah lima tahun, saya pikir pembaruan untuk membuatnya dapat dikompilasi dengan sempurna pada GHC terbaru bisa dalam rangka. Sepanjang jalan:
<$>
dan<*>
di Pendahuluan.Seperti komentar kode katakan, 5 baris (impor Data.Char, pemetaan register 8-bit, dan dump layar) tidak termasuk spesifikasi, jadi Anda dipersilakan untuk mendiskonnya jika merasa ingin :-)
sumber
.|.
? / 10charC - 7143 baris (CPU itu sendiri 3162 baris)
EDIT: Windows build sekarang memiliki menu drop-down untuk mengganti disk virtual.
Saya telah menulis emulator PC 80186 / V20 penuh (dengan CGA / MCGA / VGA, sound blaster, adlib, mouse, dll), bukanlah hal sepele untuk meniru 8086 dengan cara apa pun. Butuh berbulan-bulan untuk mendapatkan sepenuhnya akurat. Inilah modul CPU yang hanya keluar dari emulator saya.
http://sourceforge.net/p/fake86/code/ci/master/tree/src/fake86/cpu.c
Saya akan menjadi yang pertama mengakui bahwa saya menggunakan terlalu banyak variabel global dalam emulator ini. Saya mulai menulis ini ketika saya masih cukup baru untuk C, dan itu menunjukkan. Saya perlu membersihkannya beberapa hari ini. Sebagian besar file sumber lain di dalamnya tidak terlihat jelek.
Anda dapat melihat semua kode (dan beberapa tangkapan layar, satu di bawah) melalui sini: http://sourceforge.net/p/fake86
Saya akan sangat senang membantu orang lain yang ingin menulis sendiri, karena ini sangat menyenangkan, dan Anda belajar BANYAK tentang CPU! Penafian: Saya tidak menambahkan emulasi 8080 V20 karena hampir tidak pernah digunakan dalam program PC. Sepertinya banyak pekerjaan tanpa hasil.
sumber
Catatan tambahan (
130200367517531222246 baris)Masih dalam proses, tetapiSaya ingin menunjukkan beberapa kode dalam upaya mendorong orang lain untuk menunjukkan beberapa kode .Kumpulan register direpresentasikan sebagai satu string, sehingga berbagai register berukuran byte dan kata dapat secara alami tumpang tindih dengan merujuk pada substring. Substring digunakan sebagai pointer sepanjang, sehingga register dan lokasi memori (substring dari string memori) dapat diperlakukan secara seragam dalam fungsi operator.
Lalu ada beberapa kata untuk mendapatkan dan menyimpan data (byte atau kata) dari "pointer", dari memori, dari mem [(IP)] (incrementing IP). Kemudian ada beberapa fungsi untuk mengambil byte MOD-REG-R / M dan mengatur variabel REG dan R / M dan MOD, dan mendekode mereka menggunakan tabel. Kemudian fungsi operator, dikunci ke byte opcode. Jadi loop eksekusi sederhana
fetchb load exec
.Saya hanya punya sedikit opcodes yang diimplementasikan, tetapi gMendapatkan decoding operan terasa seperti tonggak sejarah sehingga saya ingin membagikannya.sunting: Menambahkan kata untuk memperpanjang nomor negatif. Lebih banyak opcodes. Perbaikan bug dalam tugas register. Komentar. Masih mengerjakan bendera dan mengisi operator. Keluaran menyajikan beberapa pilihan: teks keluaran ke stdout pada terminasi, keluaran terus menerus menggunakan kode vt100, keluaran ke jendela gambar menggunakan font CP437.
sunting: Penulisan selesai, mulai debugging. Ia mendapat empat titik keluaran pertama! Kemudian carry salah. Ngantuk.
sunting: Saya pikir saya sudah membawa Bendera Carry. Beberapa cerita terjadi di comp.lang.postscript . Saya telah menambahkan beberapa alat debugging, dan hasilnya menuju ke jendela grafik (menggunakan font-3 Jenis-3 Code-3 saya yang ditulis sebelumnya ), sehingga output teks bisa penuh dengan jejak dan dump. Itu menulis "Hello World!" dan kemudian ada tanda curiga itu. Lalu semuanya tidak ada artinya. :( Kita akan sampai di sana. Terima kasih atas semua dorongan!
sunting: Menjalankan tes hingga selesai. Beberapa bug terakhir adalah: XCHG melakukan 2 {read store} ulangi yang tentu saja salinan daripada pertukaran, DAN tidak mengatur bendera, (FE) INC mencoba untuk mendapatkan kata dari byte pointer.
sunting: Total tulis ulang dari awal menggunakan tabel ringkas dari manual ( membalik halaman baru! ). Saya mulai berpikir bahwa keluar-masuk toko dari opcode adalah ide yang buruk, tetapi itu membantu menjaga optab cantik. Tidak ada tangkapan layar saat ini. Saya menambahkan penghitung instruksi dan mod-trigger untuk membuang memori video, sehingga mudah dihubungkan dengan info debug.
sunting: Jalankan program pengujian, lagi! Beberapa bug terakhir untuk penulisan ulang yang lebih pendek lalai untuk menandatangani-memperpanjang byte langsung dalam opcodes 83 (grup "Segera") dan EB (short JMP). Peningkatan 24-baris mencakup rutinitas debug tambahan yang diperlukan untuk melacak bug-bug akhir itu.
Dan output (dengan ujung keluaran debugging disingkat).
sumber
Javascript
Saya menulis emulator 486 di javascript yang terinspirasi oleh jslinux. Jika saya tahu berapa banyak pekerjaan itu, saya mungkin tidak akan pernah memulai, tetapi sekarang saya ingin menyelesaikannya.
Lalu saya menemukan tantangan Anda dan sangat senang memiliki program 8086 untuk diuji.
Anda dapat "melihatnya" dijalankan langsung di sini: http://codinguncut.com/jsmachine/
Saya punya satu masalah saat mencetak buffer grafis. Di mana harus ada spasi, memori mengandung elemen "00". Apakah benar menafsirkan "0x00" sebagai ruang atau apakah saya memiliki bug di emulator saya?
Tepuk tangan,
Johannes
sumber
C ++
Saya ingin mengirimkan entri kami untuk tantangan kode ini. Itu ditulis dalam c ++ dan menjalankan program pengujian dengan sempurna. Kami telah menerapkan 90% dari Kode Ops One Byte dan Segmentasi Dasar (beberapa dinonaktifkan karena tidak bekerja dengan program pengujian).
Program Write Up: http://davecarruth.com/index.php/2012/04/15/creating-an-8086-emulator
Anda dapat menemukan kode dalam file zip di akhir Posting Blog.
Screenshot mengeksekusi program pengujian:
Ini butuh sedikit waktu ... jika Anda memiliki pertanyaan atau komentar maka jangan ragu untuk mengirim saya pesan. Itu tentu latihan yang bagus dalam pemrograman mitra.
sumber
ret imm
instruksinya salah (lihat di sini ) dan Anda kehilangan0xff
grup. Saya suka pesan kesalahan Anda: throw "Nilai segera tidak dapat menyimpan nilai, perlambat.";cs
registerC
Tantangan Hebat dan yang pertama. Saya membuat akun hanya karena tantangannya membuat saya sangat penasaran. Sisi buruknya adalah saya tidak bisa berhenti memikirkan tantangan ketika saya memiliki pekerjaan pemrograman yang nyata dan berbayar.
Saya merasa terdorong untuk menjalankan emulasi 8086 yang sudah selesai, tapi itu tantangan lain ;-)
Kode ini ditulis dalam ANSI-C, jadi cukup kompilasi / tautkan file .c bersama-sama, masukkan binary codegolf, dan lanjutkan.
sumber di-zip
sumber
C ++ 1064 baris
Proyek yang fantastis. Saya melakukan emulator Intellivision bertahun-tahun yang lalu, jadi itu bagus untuk melenturkan otot-otot saya yang menggedor-gedor lagi.
Setelah sekitar satu minggu bekerja, saya tidak bisa lebih bersemangat ketika ini terjadi:
Sedikit debugging nanti dan ... SHAZAM!
Juga, saya membangun kembali program pengujian asli tanpa ekstensi 80386, karena saya ingin membangun emulator saya dengan 8086 dan tidak membohongi petunjuk tambahan. Tautan langsung ke kode di sini: File zip .
Ok, saya bersenang-senang dengan ini. Saya membagi memori dan manajemen layar, dan sekarang layar diperbarui ketika buffer layar ditulis. Saya membuat video :)
http://www.youtube.com/watch?v=qnAssaTpmnA
Pembaruan: Pass pertama segmentasi sudah masuk. Sangat sedikit instruksi yang benar-benar diimplementasikan, tetapi saya mengujinya dengan menggerakkan CS / DS dan SS, dan semuanya masih berjalan dengan baik.
Juga ditambahkan penanganan interupsi yang belum sempurna. Sangat sederhana. Tapi saya menerapkan int 21h untuk mencetak string. Menambahkan beberapa baris ke sumber pengujian dan mengunggahnya juga.
Jika ada yang punya kode perakitan yang cukup sederhana yang akan menguji segmen, saya ingin bermain dengannya.
Saya mencoba mencari tahu seberapa jauh saya ingin mengambil ini. Emulasi CPU penuh? Mode VGA? Sekarang saya sedang menulis DOSBox.
12/6: Coba lihat, mode VGA!
sumber
C ++ - 4455 baris
Dan tidak, saya tidak hanya melakukan persyaratan pertanyaan. Saya melakukan SELURUH 8086, termasuk 16 opcode yang belum pernah DIKENAL. reenigne membantu menghitung opcode-opcode itu.
https://github.com/Alegend45/IBM5150
sumber
#include "cpu.h"
sulit untuk melihat.Javascript - 4.404 baris
Saya menemukan posting ini ketika meneliti informasi untuk emulator saya sendiri. Posting Codegolf ini benar-benar sangat berharga bagi saya. Program contoh dan perakitan terkait memungkinkan untuk dengan mudah men-debug dan melihat apa yang terjadi.
Terima kasih!!!
Dan ini adalah versi pertama emulator Javascript 8086 saya.
Fitur:
Demo
Saya memiliki demo online, silakan bermain dengannya dan beri tahu saya jika Anda menemukan bug :)
http://js86emu.chadrempp.com/
Untuk menjalankan program codegolf
1) klik pada tombol pengaturan
2) kemudian cukup klik muat (Anda dapat bermain dengan opsi debug di sini, seperti melangkah melalui program). Program codegolf adalah satu-satunya yang tersedia saat ini, saya sedang berusaha mendapatkan lebih banyak online.
Sumber
Sumber lengkap di sini. https://github.com/crempp/js86emu
Saya mencoba menempelkan nyali emulasi 8086 di sini (seperti yang disarankan oleh gagang pintu) tetapi melebihi batas karakter ("Badan terbatas pada 30000 karakter; Anda memasukkan 158.272").
Berikut adalah tautan cepat ke kode yang akan saya tempel di sini - https://github.com/crempp/js86emu/blob/39dbcb7106a0aaf59e003cd7f722acb4b6923d87/src/js/emu/cpus/8086.js
*Edit - updated for new demo and repo location
sumber
Jawa
Saya sudah lama ingin melakukan tantangan ini, dan akhirnya saya meluangkan waktu untuk melakukannya. Sejauh ini, ini merupakan pengalaman yang luar biasa dan saya bangga bisa mencapainya sehingga saya akhirnya menyelesaikannya.
Sumber
Kode sumber tersedia di GitHub di NeatMonster / Intel8086 . Saya telah mencoba mendokumentasikan hampir semua hal, dengan bantuan Panduan Pengguna Keluarga holly 8086 .
Saya bermaksud menerapkan semua opcodes dan fitur yang hilang, jadi Anda mungkin ingin memeriksa rilis 1.0 untuk versi dengan hanya yang diperlukan untuk tantangan ini.
Banyak terima kasih kepada @ copy!
sumber
Common Lisp - 580 loc (442 tanpa baris kosong & komentar)
Saya menggunakan tantangan ini sebagai alasan untuk mempelajari Common Lisp. Inilah hasilnya:
Inilah output di Emacs:
Saya ingin menyoroti tiga fitur utama. Kode ini membuat berat penggunaan macro ketika menerapkan petunjuk, seperti
mov
,xchg
, dan operasi artithmetic. Setiap instruksi termasukdisasm-instr
panggilan makro. Ini mengimplementasikan pembongkaran di samping kode aktual menggunakan jika variabel global ditetapkan pada saat runtime. Saya sangat bangga dengan pendekatan agnostik tujuan yang digunakan untuk menulis nilai pada register dan alamat tidak langsung. Makro yang mengimplementasikan instruksi tidak peduli dengan tujuan, karena formulir yang disambungkan untuk setiap kemungkinan akan berfungsi dengansetf
makro umum Lisp umum.Kode dapat ditemukan di repo GitHub saya . Cari cabang "codegolf", karena saya sudah mulai menerapkan fitur-fitur lain dari master 8086. Saya sudah menerapkan flag overflow dan parity, bersama dengan register FLAGS.
Ada tiga operasi dalam hal ini bukan di 8086,
0x82
dan0x83
versi operator logis. Ini tertangkap sangat terlambat, dan akan sangat berantakan untuk menghapus operasi-operasi itu.Saya ingin mengucapkan terima kasih kepada @ja untuk versi Python-nya, yang menginspirasi saya sejak awal dalam usaha ini.
sumber
C -
319348 barisIni adalah terjemahan yang kurang lebih langsung dari program Postscript saya ke C. Tentu saja penggunaan stack diganti dengan variabel eksplisit. Bidang instruksi dipecah menjadi variabel
o
- byte instruksi opcode,d
- bidang arah,w
- bidang lebar. Jika ini adalah instruksi "mod-reg-r / m", byte mr-rm dibacastruct rm r
. Decoding bidang reg dan r / m hasil dalam dua langkah: menghitung pointer ke data dan memuat data, menggunakan kembali variabel yang sama. Jadi untuk sesuatu sepertiADD AX,BX
, x pertama adalah penunjuk ke kapak dan y adalah penunjuk ke bx, maka x adalah isinya (kapak) dan y adalah isinya (bx). Ada banyak casting yang diperlukan untuk menggunakan kembali variabel untuk tipe yang berbeda seperti ini.Bytes opcode diterjemahkan dengan tabel fungsi pointer. Setiap fungsi tubuh disusun menggunakan makro untuk bagian yang dapat digunakan kembali. The
DW
makro hadir dalam semua fungsi opcode dan decoded
danw
variabel dario
byte opcode. TheRMP
makro melakukan tahap pertama decoding "mr-rm" byte, danLDXY
melakukan tahap kedua. Opcode yang menyimpan hasil menggunakanp
variabel untuk menahan pointer ke lokasi hasil danz
variabel untuk menyimpan nilai hasil. Bendera dihitung setelahz
nilainya dihitung. TheINC
danDEC
operasi menyimpan membawa bendera sebelum menggunakan generikMATHFLAGS
fungsi (sebagai bagian dariADD
atauSUB
submacro) dan kembalikan kata penutupnya, untuk menjaga Carry.Edit: bug diperbaiki!
Edit: diperluas dan dikomentari. Saat
trace==0
ini menampilkan perintah ANSI move-to-0,0 saat membuang video. Jadi lebih baik mensimulasikan tampilan yang sebenarnya. BendaBIGENDIAN
(yang bahkan tidak berfungsi) telah dihapus. Itu bergantung di beberapa tempat pada urutan byte little-endian, tapi saya berencana untuk memperbaikinya di revisi berikutnya. Pada dasarnya, semua akses pointer harus melaluiget_
danput_
fungsi - fungsi yang secara eksplisit (de) menyusun byte dalam urutan LE.Menggunakan makro untuk tahapan berbagai operasi membuat pertandingan semantik yang sangat dekat dengan cara kode postscript beroperasi secara murni berurutan. Sebagai contoh, empat opcodes pertama, 0x00-0x03 adalah semua instruksi ADD dengan arah yang berbeda-beda (REG -> REG / MOD, REG <- REG / MOD) dan ukuran byte / kata, sehingga mereka direpresentasikan sama persis di tabel fungsi .
Tabel fungsi dipakai dengan makro ini:
yang berlaku
OPF()
untuk setiap representasi opcode.OPF()
didefinisikan sebagai:Jadi, empat opcodes pertama berkembang (sekali) ke:
Fungsi-fungsi ini membedakan diri mereka sendiri dengan hasil
DW
makro yang menentukan arah dan bit byte / kata langsung dari byte opcode. Memperluas tubuh dari salah satu fungsi ini (sekali) menghasilkan:Di mana loop utama telah menetapkan
o
variabel:Memperluas sekali lagi memberikan semua "daging" opcode:
Dan fungsi yang sepenuhnya diproses sebelumnya, melewati
indent
:Bukan gaya C terbaik untuk penggunaan sehari-hari, tetapi menggunakan makro dengan cara ini tampaknya cukup sempurna untuk membuat implementasi di sini sangat singkat dan sangat langsung.
Keluaran program uji, dengan ekor keluaran jejak:
Saya membagikan beberapa versi sebelumnya di comp.lang.c tetapi mereka tidak terlalu tertarik.
sumber
indent
ed 5810 baris.