Arka fon
Eski 8-bit 6502 çipimi seviyorum. 6502 makine kodunda PPCG'deki bazı zorlukları çözmek bile eğlenceli. Ancak basit olması gereken bazı şeyler (veri okuma veya stdout çıktısı gibi) makine kodunda gereksiz yere zahmetlidir. Yani aklımda kaba bir fikir var: 6502'den ilham alan kendi 8-bit sanal makinemi icat et, ancak tasarım zorluklar için daha kullanışlı olacak şekilde değiştirildi. Bir şeyleri uygulamaya başlayarak, VM'nin tasarımı tamamen minimuma indirilirse bunun kendisinin güzel bir zorluk olabileceğini fark ettim :)
Görev
Aşağıdaki özelliklere uygun 8 bitlik sanal bir makine uygulayın. Bu kod golf , bu yüzden en az bayt olan uygulama kazanır.
Giriş
Uygulamanız aşağıdaki girdileri almalıdır:
Tek bir imzasız bayt
pc
, bu ilk program sayacıdır (VM'nin yürütmeye başladığı bellekteki adres,0
temelli)Maksimum giriş uzunluğuna sahip bir bayt listesi
256
, bu sanal makine için RAM'dir (başlangıç içeriği ile)
Bu girişi herhangi bir makul biçimde alabilirsiniz.
Çıktı
VM sona erdikten sonra RAM'in son içeriği olan baytların listesi (aşağıya bakınız). Sonunda yalnızca sona erdirmeye yol açan girdiler aldığınızı varsayabilirsiniz. Herhangi bir mantıklı formata izin verilir.
Sanal işlemci
Sanal işlemci var
- 8 bitlik program sayacı,
- adı verilen 8 bitlik bir akümülatör kaydı
A
ve - adı verilen 8 bitlik bir dizin kaydı
X
.
Üç durum bayrağı vardır:
Z
- Sıfır bayrağı bazı işlemlerin sonuçlanmasından sonra ayarlanır.0
N
- Negatif bayrak, bazı işlemlerin negatif bir sayıyla sonuçlanmasından sonra ayarlanır (sonucun iow bit 7'si ayarlanır)C
- taşıma bayrağı sonucun "eksik" kısmı için toplama ve kaymalar ile belirlenir
Başlaması üzerine, bayraklar tüm program sayacı belirli bir değeri ve içeriğine ayarlanır, silinir A
ve X
belirsiz bulunmaktadır.
8 bitlik değerler
- Bir işaretsiz arasında bir tam sayı
[0..255]
- Bir imzalı aralıkta tamsayı, 2'ye tümleme,
[-128..127]
bağlama bağlı olarak. Bir işlemin üstünden veya altından geçmesi durumunda, değer etrafına sarılır (ve ilave olması durumunda taşıma bayrağı etkilenir).
Sonlandırma
Sanal makine ne zaman sona erer?
- Bir
HLT
eğitime ulaşıldı - Mevcut olmayan bir hafıza adresine erişildi.
- Program sayacı hafızanın dışında çalışır (VM'ye tam 256 byte hafıza verilmiş olsa bile etrafına sarılmadığını unutmayın)
Adresleme modları
- örtülü - komutun argümanı yok, işlenen ima edildi
- acil - işlenen komuttan hemen sonra bayt olur
- göreceli - (yalnızca dallanma için) komut imzalandıktan sonra bayt (2'nin tamamlayıcısı) ve dal alındığında program sayacına eklenecek dengeyi belirler.
0
aşağıdaki talimatın yeri - kesin - komuttan sonraki bayt işlenenin adresidir
- İndekslenmiş - komut artıdan sonraki bayt
X
(kayıt) işlenenin adresidir
Talimatlar
Her komut bir opcode (bir bayt) ve adresleme modlarında anında , göreceli , mutlak ve ikinci bir argüman baytını indekslenmiş olarak içerir . Sanal CPU bir komut çalıştırdığında, program sayacını buna göre arttırır ( 1
veya2
).
Burada gösterilen tüm kodlar hex cinsindendir.
LDA
- içine işlenen yükA
- Kodlar: anında:,
00
mutlak:,02
dizinlenmiş:04
- Bayraklar:
Z
,N
- Kodlar: anında:,
STA
-A
operand içine saklamak- Kodlar: anında:,
08
mutlak:,0a
dizinlenmiş:0c
- Kodlar: anında:,
LDX
- içine işlenen yükX
- Kodlar: anında:,
10
mutlak:,12
dizinlenmiş:14
- Bayraklar:
Z
,N
- Kodlar: anında:,
STX
-X
operand içine saklamak- Kodlar: anında:,
18
mutlak:,1a
dizinlenmiş:1c
- Kodlar: anında:,
AND
- bitsel ve içindeA
ve içine işlenenA
- Kodlar: anında:,
30
mutlak:,32
dizinlenmiş:34
- Bayraklar:
Z
,N
- Kodlar: anında:,
ORA
- bit düzeyinde ya aitA
ve içine, işlenenA
- Kodlar: anında:,
38
mutlak:,3a
dizinlenmiş:3c
- Bayraklar:
Z
,N
- Kodlar: anında:,
EOR
- bitsel xor (özel veya)A
ve operandA
- Kodlar: anında:,
40
mutlak:,42
dizinlenmiş:44
- Bayraklar:
Z
,N
- Kodlar: anında:,
LSR
- Mantıksal sağa kayma, işlenenin tüm bitlerini bir sağa kaydırın, bit 0 devam eder- Kodlar: anında:,
48
mutlak:,4a
dizinlenmiş:4c
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
ASL
- aritmetik sola kaydırma, işlenenin tüm bitlerini bir yerde sola kaydırma, bit 7 taşımaya gider- Kodlar: anında:,
50
mutlak:,52
dizinlenmiş:54
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
ROR
- sağa dönün, tüm işlenenin bitlerini bir yere sağa kaydırın, taşıma bit 7'ye gider, bit 0 taşınmaya gider- Kodlar: anında:,
58
mutlak:,5a
dizinlenmiş:5c
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
ROL
- sola dönün, işlemcinin tüm bitlerini bir yerden sola kaydırın, taşıma biti 0'a, biti 7 taşımaya gider- Kodlar: anında:,
60
mutlak:,62
dizinlenmiş:64
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
ADC
- taşıma ile ekle, işlenen artı taşıma eklenirA
, taşıma taşma üzerine kurulur- Kodlar: anında:,
68
mutlak:,6a
dizinlenmiş:6c
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
INC
- operand bir artış- Kodlar: anında:,
78
mutlak:,7a
dizinlenmiş:7c
- Bayraklar:
Z
,N
- Kodlar: anında:,
DEC
- birer birer operand azalması- Kodlar: anında:,
80
mutlak:,82
dizinlenmiş:84
- Bayraklar:
Z
,N
- Kodlar: anında:,
CMP
-A
operand'ı çıkartarak operand ile karşılaştırmakA
, sonucu unutmak. Taşıma işlemi akış altında temizlendi, aksi takdirde ayarlandı- Kodlar: anında:,
88
mutlak:,8a
dizinlenmiş:8c
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
CPX
- KarşılaştırmaX
- aynıCMP
içinX
- Kodlar: anında:,
90
mutlak:,92
dizinlenmiş:94
- Bayraklar:
Z
,N
,C
- Kodlar: anında:,
HLT
- sonlandır- Kodlar: kapalı:
c0
- Kodlar: kapalı:
INX
- artışX
tarafından- Kodlar: kapalı:
c8
- Bayraklar:
Z
,N
- Kodlar: kapalı:
DEX
- eksiltmeX
teker- Kodlar: kapalı:
c9
- Bayraklar:
Z
,N
- Kodlar: kapalı:
SEC
- taşıma bayrağı ayarla- Kodlar: kapalı:
d0
- Bayraklar:
C
- Kodlar: kapalı:
CLC
- açık taşıma bayrağı- Kodlar: kapalı:
d1
- Bayraklar:
C
- Kodlar: kapalı:
BRA
- şube her zaman- Opcodes: göreceli:
f2
- Opcodes: göreceli:
BNE
-Z
bayrak temizlenirse dal- Opcodes: göreceli:
f4
- Opcodes: göreceli:
BEQ
-Z
bayrak ayarlanmışsa dal- Opcodes: göreceli:
f6
- Opcodes: göreceli:
BPL
-N
bayrak temizlenirse dal- Opcodes: göreceli:
f8
- Opcodes: göreceli:
BMI
-N
bayrak ayarlanmışsa dal- Opcodes: göreceli:
fa
- Opcodes: göreceli:
BCC
-C
bayrak temizlenirse dal- Opcodes: göreceli:
fc
- Opcodes: göreceli:
BCS
-C
bayrak ayarlanmışsa dal- Opcodes: göreceli:
fe
- Opcodes: göreceli:
opcodes
Yukarıdaki listeden geçerli bir talimat ile eşleşmeyen herhangi bir opcode bulunursa, VM'nin davranışı tanımlanmaz.
Gereğince Jonathan Allan isteği , sen olabilir yerine gösterilen opcodes opcodes Kendi tercih kılavuzu bölümünde. Bunu yaparsan, yapmalısın Cevabınız yukarıda kullanılan opcodes tam eşleme ekleyin.
Eşleme, çiftli bir onaltılık dosya olmalıdır <official opcode> <your opcode>
, örneğin, iki işlem kodunu değiştirdiyseniz:
f4 f5
10 11
Newlines burada önemli değil.
Test vakaları (resmi kodlamalar)
// some increments and decrements
pc: 0
ram: 10 10 7a 01 c9 f4 fb
output: 10 20 7a 01 c9 f4 fb
// a 16bit addition
pc: 4
ram: e0 08 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01
output: 0a 0b 2a 02 02 00 6a 02 0a 00 02 01 6a 03 0a 01
// a 16bit multiplication
pc: 4
ram: 5e 01 28 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
02 62 03 c9 f8 e6 c0 00 00
output: 00 00 00 00 10 10 4a 01 5a 00 fc 0d 02 02 d1 6a 21 0a 21 02 03 6a 22 0a 22 52
02 62 03 c9 f8 e6 c0 b0 36
Daha sonra daha fazla test çantası ekleyebilirim.
Referans ve test
Kendi denemelerine yardımcı olmak için işte bazı (tamamen golf oynamayan) referans uygulaması - izleme bilgilerini (demonte talimatlar dahil) verebilir.stderr
ve bunları dönüştürebilir.
Kaynak almanın önerilen yolu:
git clone https://github.com/zirias/gvm --branch challenge --single-branch --recurse-submodules
Veya ödeme şubesi challenge
ve birgit submodule update --init --recursive
sistemimi almak için klonladıktan sonra yapın.
Aracı GNU make ile oluşturun (yalnızca yazın make
veya gmake
sisteminizde varsayılan make GNU make değil).
Kullanım :gvm [-s startpc] [-h] [-t] [-c convfile] [-d] [-x] <initial_ram
-s startpc
- ilk program sayacı, varsayılan olarak0
-h
- giriş onaltılık (aksi durumda ikili)-t
- icra takibistderr
-c convfile
- kodları belirtilen haritaya göre dönüştürconvfile
-d
- sonuçtaki belleği ikili veri olarak çıkar-x
- elde edilen belleği hex olarakinitial_ram
- başlangıçtaki RAM içeriği, onaltılı veya ikili
Dönüştürme özelliğinin çalışırken kodları değiştiren programlarda başarısız olacağını unutmayın .
Feragatname: Yukarıdaki kurallar ve şartnameler bu araç için değil meydan okuma için yetkilidir. Bu özellikle opcode dönüştürme özelliği için geçerlidir. Burada sunulan aracın teknik özelliklerde bir hata olduğunu düşünüyorsanız, lütfen bir yorumda bulunun :)
BRA
( "her zaman şube") kontrol akışında bir şube tanıtmak değil, o denilen olmamalıdır JMP
?
BRA
önce 65C02 ve MC 68000 gibi yonga tasarımlarında (6502'nin böyle bir talimatı yoktur) JMP
vardır. Fark, BRA
göreceli adresleme ve JMP
mutlak adreslemedir. Bu yüzden, sadece bu tasarımları takip ettim - aslında, bu kadar mantıklı gelmiyor;)