Emülasyon çok yönlü bir alandır. İşte temel fikirler ve fonksiyonel bileşenler. Bunu parçalara ayıracağım ve daha sonra ayrıntıları düzenlemelerle dolduracağım. Anlatacağım şeylerin çoğu, işlemcilerin iç işleri hakkında bilgi gerektirecektir - montaj bilgisi gereklidir. Eğer bazı şeyler konusunda biraz fazla muğlaksam, lütfen bu soruyu geliştirmeye devam edebilmek için sorular sorun.
Temel fikir:
Emülasyon, işlemcinin ve bileşenlerin davranışlarını işleyerek çalışır. Sistemin her bir parçasını inşa edersiniz ve daha sonra parçaları kabloda olduğu gibi donanıma bağlarsınız.
İşlemci emülasyonu:
İşlemci öykünmesini işlemenin üç yolu vardır:
- yorumlama
- Dinamik yeniden derleme
- Statik yeniden derleme
Tüm bu yollarda aynı genel hedefiniz vardır: işlemci durumunu değiştirmek ve 'donanım' ile etkileşimde bulunmak için bir kod parçası yürütün. İşlemci durumu, belirli bir işlemci hedefi için işlemci kayıtlarının, kesme işleyicilerinin vb. Bir araya getirilmesidir. 6502 için, kayıtlarını temsil 8 bitlik tamsayılar bir dizi olurdu: A
, X
, Y
, P
, ve S
; ayrıca 16 bitlik bir PC
kaydınız olur.
Yorumlama ile IP
(talimat işaretçisi - aynı zamanda PC
program sayacı olarak da adlandırılır ) başlar ve talimatı bellekten okursunuz. Kodunuz bu talimatı ayrıştırır ve bu bilgileri işlemcinizin belirttiği şekilde işlemci durumunu değiştirmek için kullanır. Yorumlamanın temel sorunu çok yavaş olmasıdır; Belirli bir talimatı her ele aldığınızda, kodu çözmeniz ve gerekli işlemi yapmanız gerekir.
Dinamik yeniden derleme ile, kod üzerinde yorumlama gibi yinelenirsiniz, ancak sadece opcodes yürütmek yerine bir işlem listesi oluşturursunuz. Şube komutuna ulaştığınızda, bu işlem listesini ana makine platformunuz için makine koduna derlersiniz, daha sonra bu derlenmiş kodu önbelleğe alır ve yürütürsünüz. Ardından, belirli bir talimat grubuna tekrar bastığınızda, kodu yalnızca önbellekten yürütmeniz gerekir. (BTW, çoğu insan aslında bir talimat listesi yapmaz, ancak bunları anında makine koduna derler - bu optimize etmeyi daha zor hale getirir, ancak yeterli kişi ilgilenmedikçe bu cevabın kapsamı dışındadır)
Statik yeniden derleme ile dinamik yeniden derleme ile aynı şeyi yaparsınız, ancak dalları takip edersiniz. Programdaki tüm kodu temsil eden bir kod yığını oluşturursunuz ve bu kod daha sonra herhangi bir müdahale olmadan yürütülebilir. Aşağıdaki sorunlar olmasaydı bu harika bir mekanizma olurdu:
- Başlamak için programda olmayan kod (örneğin, sıkıştırılmış, şifrelenmiş, çalışma zamanında oluşturulmuş / değiştirilmiş, vb.) Kod yeniden derlenmeyeceğinden, çalışmaz
- Belirli bir ikili dosyadaki tüm kodu bulmanın Durdurma sorununa eşdeğer olduğu kanıtlanmıştır.
Bunlar, vakaların% 99'unda statik yeniden derlemeyi tamamen olanaksız hale getirmek için birleştirilir. Daha fazla bilgi için, Michael Steil statik yeniden derleme konusunda büyük araştırmalar yaptı - gördüğüm en iyisi.
İşlemci öykünmesinin diğer tarafı, donanımla etkileşim biçiminizdir. Bunun gerçekten iki tarafı var:
- İşlemci zamanlaması
- Kesinti işleme
İşlemci zamanlaması:
Bazı platformlar - özellikle NES, SNES gibi eski konsollar - öykünücünüzün tamamen uyumlu olması için sıkı zamanlama gerektiriyor. NES ile, CPU'nun pikselleri kesin anlarda belleğe koymasını gerektiren PPU'ya (piksel işleme birimi) sahip olursunuz. Yorum kullanırsanız, döngüleri kolayca sayabilir ve uygun zamanlamayı taklit edebilirsiniz; dinamik / statik yeniden derleme ile işler bir / lot / daha karmaşıktır.
Kesinti işleme:
Kesmeler, CPU'nun donanım ile iletişim kurduğu birincil mekanizmadır. Genel olarak, donanım bileşenleriniz CPU'ya neyin önem verdiği kesintileri söyleyecektir. Bu oldukça basittir - kodunuz belirli bir kesmeyi attığında, kesme işleyici tablosuna bakar ve uygun geri aramayı çağırırsınız.
Donanım öykünmesi:
Belirli bir donanım aygıtını taklit etmenin iki tarafı vardır:
- Cihazın işlevselliğini taklit etme
- Gerçek cihaz arayüzlerini taklit etme
Bir sabit sürücü kasasını alın. Bu işlevsellik, destek depolama, okuma / yazma / formatlama yordamları vb. Oluşturularak taklit edilir. Bu bölüm genellikle çok basittir.
Cihazın gerçek arayüzü biraz daha karmaşıktır. Bu genellikle bellek eşlemeli kayıtların bir kombinasyonudur (örneğin cihazın sinyalleme değişikliklerini izlemek için izlediği bellek parçaları) ve kesintilerdir. Bir sabit sürücü için, okuma komutları, yazılar vb. Yerleştirdiğiniz ve bu verileri geri okuduğunuz bir bellek eşlemeli alanınız olabilir.
Daha fazla ayrıntıya girerdim, ama bununla baş edebilmenin bir milyon yolu var. Burada herhangi bir sorunuz varsa, sormaktan çekinmeyin, ben de bilgileri ekleyeceğim.
Kaynaklar:
Ben intro burada oldukça iyi verdik düşünüyorum, ama bir orada tonluk ek alanların. Herhangi bir soruya yardımcı olmaktan mutluluk duyuyorum; Bunun çoğunda, sadece büyük karmaşıklıktan dolayı çok belirsiz davrandım.
Zorunlu Wikipedia bağlantıları:
Genel öykünme kaynakları:
- Zophar - Burası öykünme ile başladım, ilk önce emülatörleri indirdim ve sonunda büyük belge arşivlerini yağmaladım. Bu, sahip olabileceğiniz mutlak en iyi kaynaktır.
- NGEmu - Çok fazla doğrudan kaynak yok, ancak forumları rakipsiz.
- RomHacking.net - Belgeler bölümü, popüler konsollar için makine mimarisine ilişkin kaynakları içerir
Referans edilecek emülatör projeleri:
- IronBabel - Bu Nemerle yazılmış .NET için bir öykünme platformu ve anında kod C # derler. Yasal Uyarı: Bu benim projem, bu yüzden utanmaz fişi affedin.
- BSnes - Mükemmel döngü doğruluğu hedefiyle harika bir SNES emülatörü.
- MAME - çarşı emülatörü. Harika referans.
- 6502asm.com - Bu harika bir forum ile bir JavaScript 6502 emülatörüdür.
- dynarec'd 6502asm - Bu bir iki gün içinde yaptığım küçük bir hack. Mevcut emülatörü 6502asm.com'dan aldım ve devasa hız artışları için kodu dinamik olarak JavaScript'e yeniden derleyecek şekilde değiştirdim.
İşlemci yeniden derleme başvuruları:
- Michael Steil (yukarıda atıfta bulunulan) tarafından yapılan statik yeniden derleme araştırması bu makalede doruğa ulaşmıştır ve burada kaynak ve benzeri bulabilirsiniz .
Zeyilname:
Bu cevabın gönderilmesinden bu yana bir yıldan fazla bir süre geçti ve aldığı tüm dikkatle bazı şeyleri güncelleme zamanının geldiğini düşündüm.
Belki de şu anda emülasyondaki en heyecan verici şey , yukarıda bahsedilen Michael Steil tarafından başlatılan libcpu . Yeniden derleme için LLVM kullanan (statik ve dinamik!) Çok sayıda CPU çekirdeğini desteklemeyi amaçlayan bir kütüphanedir. Büyük bir potansiyele sahip ve bence öykünme için harika şeyler yapacak.
emu-docs da dikkatimi çekti, bu da emülasyon amaçları için çok yararlı olan sistem belgelerinin büyük bir havuzunu barındırıyor. Orada fazla zaman geçirmedim, ama çok büyük kaynakları var gibi görünüyor.
Bu yazının yararlı olduğuna sevindim ve kıçımdan inip yılın sonunda / gelecek yılın başlarında konu hakkındaki kitabımı bitirebileceğimi umuyorum.