Makine kodu farklı bir mimariye çevrilebilir mi?


11

Yani bu, ARM'de bir Windows sunucusu çalıştırmakla ilgili bir soru ile ilgilidir . Benim sorumun temel nedeni, makine kodunun üzerinde çalışmak için derlendiğinden farklı bir mimaride bir ikili yürütmek için bir mimariden diğerine çevrilebilir mi?

QEMU ve diğer emülatörler, talimatları anında çevirebilir ve bu nedenle derlenmediği bir bilgisayarda yürütülebilir bir dosya çalıştırabilir. Süreci hızlandırmak için neden bu çeviriyi anında yapmak yerine yapmıyorsunuz? Montaj benim biraz sınırlı bilgiden, talimatları çoğu gibi MOV, ADDve diğerleri altyapısılerinde taşınabilir olmalıdır.

Doğrudan bir eşlemesi olmayan herhangi bir şey, tüm makineler Turing Complete olduğundan diğer bazı talimatlarla eşlenebilir. Bunu yapmak çok karmaşık olur mu? Bilmiyorum nedense hiç işe yaramaz mı? Çalışır, ancak bir emülatör kullanmaktan daha iyi sonuç vermez mi?


Teknik muhtemelen hoşnutsuzluğa düştü, çünkü (lapa lapa ek olarak) çok fazla gerekmiyor. Taşınabilirlik / standardizasyon bu günlerde (biraz daha iyi) (yalnızca Wintel dünyayı ele geçirdiği için) ve çapraz makine emülasyonunun gerçekten gerekli olduğu durumlarda (örneğin, bir uygulama geliştirme ortamında bir telefon emülatörü için), doğrudan emülasyon daha güvenilir ve doğru sonuç. Ayrıca, işlemciler öykünme maliyetinin geçmişte olduğu kadar ciddi bir sorun olmayacak kadar hızlıdır.
Daniel R Hicks

Yanıtlar:


6

Kısa cevap : Derlenmiş, bağlantılı bir çalıştırılabilir dosyayı çeviremezsiniz. Teknik olarak mümkün olmakla birlikte, başarılması son derece imkansızdır (aşağıya bakınız). Ancak , derleme kaynak dosyanız varsa (yönergeleri ve etiketleri içerir), (program kaynağında bir şekilde elde ederseniz, program derlemede yazılmadığı sürece, orijinal program kaynak koduna sahip olmanız gerekir) yani, farklı mimarinin başlaması için onu derlemeniz daha iyi olur).


Uzun cevap :

QEMU ve diğer emülatörler, talimatları anında çevirebilir ve bu nedenle derlenmediği bir bilgisayarda yürütülebilir bir dosya çalıştırabilir. Süreci hızlandırmak için neden bu çeviriyi anında yapmak yerine yapmıyorsunuz?

Prensip olarak kolay göründüğünü biliyorum, ama pratikte, birkaç ana nedenden dolayı neredeyse imkansız. Başlamak için, farklı komut setleri büyük ölçüde farklı adresleme modları, farklı opcode yapıları, farklı kelime boyutları kullanır ve bazılarında ihtiyacınız olan talimatlar bile yoktur.

Diyelim ki talimatı XYZiki talimatla değiştirmeniz gerekiyor ABCve DEF. Şimdi, tüm programdaki tüm göreli / ofset adreslerini bu noktadan itibaren etkili bir şekilde kaydırdınız, bu nedenle tüm programı analiz etmeniz ve geçmeniz ve ofsetleri (değişiklikten önce ve sonra) güncellemeniz gerekir. Şimdi, ofsetlerden birinin önemli ölçüde değiştiğini varsayalım - şimdi adresin boyutunu değiştirebilecek adresleme modlarını değiştirmeniz gerekiyor. Bu, sizi tüm dosyayı yeniden taramaya ve tüm adresleri yeniden hesaplamaya vb. Zorlar.

Montaj programları yazdığınızda etiketleri kullanabilirsiniz, ancak CPU kullanmaz - dosya birleştirildiğinde, tüm etiketler göreli, mutlak veya ofset konumları olarak hesaplanır. Bunun neden hızla önemsiz bir görev haline geldiğini ve imkansızın yanında görebilirsiniz. Tek bir talimatın değiştirilmesi, devam etmeden önce tüm programdan yüzlerce kez geçmenizi gerektirebilir.

Biraz sınırlı montaj bilgimden, MOV, ADD ve diğerleri gibi talimatların çoğu mimariler arasında taşınabilir olmalıdır.

Evet, ancak yukarıda özetlediğim konulara bakın. Makinenin kelime boyutu ne olacak? Adres uzunluğu? Aynı adresleme modlarına bile sahip mi? Yine, sadece talimatları "bulamaz ve değiştiremezsiniz". Bir programın her bölümünün özel olarak tanımlanmış bir adresi vardır. Bir program kurulduğunda diğer etiketlere atlamalar gerçek veya ofset bellek adresleriyle değiştirilir.

Doğrudan bir eşlemesi olmayan herhangi bir şey, tüm makineler Turing Complete olduğundan diğer bazı talimatlarla eşlenebilir. Bunu yapmak çok karmaşık olur mu? Bilmiyorum nedense hiç işe yaramaz mı? Çalışır, ancak bir emülatör kullanmaktan daha iyi sonuç vermez mi?

Her ikisinin de mümkün olduğu ve çok daha hızlı olacağı için % 100 haklısınız . Ancak, bunu gerçekleştirmek için bir program yazmak, yukarıda özetlediğim konular dışında bir şey olmasa bile, inanılmaz derecede zor ve son derece imkansızdır.

Gerçek montaj kaynak koduna sahip olsaydınız, makine kodunu başka bir talimat kümesi mimarisine çevirmek önemsiz olurdu. Bununla birlikte, makine kodunun kendisi monte edilir , bu nedenle montaj kaynağı (bellek adreslerini hesaplamak için kullanılan çeşitli etiketler içerir) olmadan, inanılmaz derecede zorlaşır. Yine, tek bir komutun değiştirilmesi tüm programdaki bellek ofsetlerini değiştirebilir ve adresleri yeniden hesaplamak için yüzlerce geçiş gerektirebilir.

Bunu birkaç bin talimatı olan bir program için yapmak, yüz binlerce geçiş olmasa bile onlarca gerektirir. Nispeten küçük programlar için bu mümkün olabilir, ancak geçiş sayısının programdaki makine talimatlarının sayısı ile katlanarak artacağını unutmayın. Yeterince iyi bir boyutta herhangi bir program için, neredeyse imkansızdır.


Esasen birinin kaynak nesne kodunu "kaynak koda dönüştürmek" veya "sökmek" dir. Nispeten düz ileri kod (özellikle, bilinen bir "stil" olan belirli derleyiciler veya kod oluşturma paketleri tarafından üretilen kod) için etiketlerin ve benzerinin yeniden takılması oldukça basittir. Bununla birlikte, şüphesiz, daha yeni optimize edilmiş derleyiciler bu şekilde "toparlamak" için çok daha zor olan kodlar üretecektir.
Daniel R Hicks

@DanH Kaynak nesne koduna sahipseniz, hemen hemen montaj kaynağına sahipsiniz ( makine kodu değil ). Nesne dosyası, birbirine bağlanacak makine kodunun adlandırılmış (okuma: etiketli) dizilerini içerir. Sorun, nesne kodu dosyalarını yürütülebilir bir dosyaya bağladığınızda gelir. Bu daha küçük segmentler, bağlantılı tüm yürütülebilir dosyadan çok daha kolay işlenebilir (veya tersine mühendislik yapılabilir).
Atılım

Elbette, bazı nesne dosya formatları işi biraz daha kolaylaştırır. Bazıları etiketlerin çoğunu geri yüklemenizi sağlayan hata ayıklama bilgileri bile içerebilir. Diğerleri daha az yardımcı olur. Bazı durumlarda, bu bilgilerin çoğu bağlantılı dosya biçiminde bile korunur, bazı durumlarda korunmaz. Çok sayıda farklı dosya formatı vardır.
Daniel R Hicks

2

Evet, önerdiğiniz şey yapılabilir ve yapılmıştır. Çok yaygın değil ve tekniği kullanan mevcut sistemleri bilmiyorum, ama kesinlikle teknik fizibilite alanında iyi.

Herkesin sahip olduğumuz kaba "taşınabilirliği" elde etmeden önce kodun bir sistemden diğerine taşınmasını sağlamak için çok şey yapıldı. "Kaynak" ın karmaşık analizini gerektiriyordu ve kod değişikliği ve diğer garip uygulamalar tarafından uyarılabilirdi, ama yine de yapıldı.

Daha yakın zamanlarda, IBM System / 38 - iSeries - System i gibi sistemler, uyumsuz komut seti mimarileri arasında taşınabilirliği sağlamak için derlenmiş programlarla depolanan ara kodun (Java bayt kodlarına benzer) taşınabilirliğinden yararlanmıştır.


Bunun daha eski (daha basit) komut kümeleriyle yapıldığını kabul edin. 1970'lerde eski 7xx ikili programları System / 360'a dönüştürmek için bir IBM projesi vardı.
talaş

1

Makine kodunun kendisi mimariye özgüdür.

Birden fazla mimaride kolay taşınabilirliğe izin veren diller (Java muhtemelen en iyi bilinir) çok yüksek seviyededir ve çalışabilmeleri için bir makineye tercüman veya çerçeve kurulmasını gerektirir.

Bu çerçeveler veya tercümanlar, üzerinde çalışacakları her bir sistem mimarisi için yazılmıştır ve bu nedenle kendi başlarına "normal" bir programdan daha taşınabilir değildir.


2
Derlenmiş diller de sadece yorumlanmış diller değil, taşınabilirdir, nihayetinde kodu platformun tanıyabileceği şeye çeviren mimariye özgü derleyicidir. Tek fark, derlenen dillerin derleme zamanında çevrilmesi ve yorumlanan dillerin satır satır gerektiği gibi çevrilmesidir.
MaQleod

1

Kesinlikle, bu mümkün. Makine kodu nedir? Bu sadece dilbelirli bir bilgisayarın anladığı. Kendinizi bilgisayar olarak düşünün ve Almanca yazılmış bir kitabı anlamaya çalışıyorsunuz. Bunu yapamazsın, çünkü dili anlamıyorsun. Şimdi bir Almanca sözlük alıp "Kopf" kelimesine baksaydınız, bu kelimenin İngilizce "head" kelimesine çevrildiğini görürdünüz. Kullandığınız sözlüğe bilgisayar dünyasında öykünme katmanı denir. Kolay değil mi? Daha da zorlaşıyor. Almanca "Schadenfruede" kelimesini alın ve İngilizce'ye çevirin. İngilizce dilinde bir kelime olmadığını göreceksiniz, ancak bir tanım var. Aynı problem bilgisayar dünyasında da eşdeğer bir kelimeye sahip olmayan şeyleri tercüme ediyor. Öykünme katmanı geliştiricilerinin bu kelimenin ne anlama geldiğini yorumlaması ve ana bilgisayarı anlaması için doğrudan bağlantı noktalarını zorlaştırır. Bazen sadece beklendiği gibi çalışmaz. İnternette kitapların, deyimlerin vb. Komik çevirilerini gördük değil mi?


1

Açıkladığınız işleme Statik Yeniden Derleme denir ve bu genellikle uygulanabilir bir şekilde değil yapılır. Yani mümkün değil, birçok kez yapıldı, ancak manuel çalışma gerektiriyordu.

Araştırmaya değer birçok tarihsel örnek var, ancak modern endişeleri daha az gösterebiliyorlar. Herhangi bir şüpheciyi her şeyin zor olduğunu iddia eden insanları sorgulamak için esasen imkansız kılan iki örnek buldum.

İlk olarak bu adam bir NES ROM için tam bir Statik Mimarlık ve Platform yaptı. http://andrewkelley.me/post/jamulator.html

Bazı çok iyi puanlar veriyor, ancak JIT'in hala daha pratik olduğu sonucuna varıyor. Aslında bu durum için neden çoğu insanın düşündüğü bir durum olabileceğini bilmiyor olduğundan emin değilim. Hiçbir kısayol alma, tam döngü doğruluğu talep etme ve aslında hiç ABI kullanma. Her şey olsaydı, kavramı çöpe atabilir ve bir gün diyebiliriz, ama hepsi değil ve asla değildi ... Bunu nasıl bilebiliriz? Çünkü tüm başarılı projeler bu yaklaşımı kullanmadı.

Şimdi daha az açık olan olasılıklar için, Sahip olduğunuz platformdan yararlanın ... Linux ARM cihazında Starcraft? Evet, yaklaşım, görevi tam olarak dinamik olarak yapacağınız şeyle sınırlamadığınız zaman işe yarar. Winlib'i kullanarak Windows platform çağrıları tamamen yereldir, endişelenmemiz gereken tek şey Mimari'dir.

http://www.geek.com/games/starcraft-has-been-reverse-engineered-to-run-on-arm-1587277/

ARM avuçiçi pandora'nın Pi'den biraz daha güçlü olduğu göz önüne alındığında, donutlara yavaşlamanın neredeyse önemsiz olduğu dolar atıyorum. Kullandığı araçlar bu depoda.

https://github.com/notaz/ia32rtools

Bu adam çok elle ayrıştı, sürecin daha az işle önemli ölçüde otomatikleştirilebileceğine inanıyorum ... ama şu anda hala bir aşk emeği. Kimsenin size bir şeyin mümkün olmadığını söylemesine izin vermeyin, bunun pratik olmadığını söylememe bile izin vermeyin ... Bunu yapmak için yeni bir yöntem geliştirdiğinizde pratik olabilir.


0

Teorik olarak, evet bu yapılabilir. Ortaya çıkan en büyük sorun, bir işletim sistemi (veya çekirdek) için bir uygulamayı diğerine çevirmektir. Windows, Linux, OSX ve iOS çekirdeği düşük seviyeli işlemleri arasında, bu cihazların tüm uygulamalarının kullanması gereken önemli farklılıklar vardır.

Bir kez daha, teorik olarak, bir uygulamanın yanı sıra çalıştırılmak üzere derlendiği işletim sistemi ile ilişkili tüm makine kodunun yanı sıra bu makine kodunun tümünü başka bir cihaz için yeniden derleyebilen bir uygulama da yazılabilir. Ancak, bu hemen hemen her durumda oldukça yasadışı olurdu ve yazmak son derece zor olurdu. Aslında, kafamdaki dişliler sadece düşünerek ele geçirmeye başlıyor.

GÜNCELLEME

Aşağıdaki yorumlardan birkaçı benim yanıtımla aynı fikirde değil gibi görünüyor, ancak bence bu konuya değinmiyorlar. Bildiğim kadarıyla, bir mimari için yürütülebilir bayt dizisi alabilen, onu temel OS çekirdeğine çağrılar ve başka bir sistem için yeniden birleştiren dahil ekstrnal kütüphanelere gerekli tüm çağrıları içeren bayt kodu düzeyinde ayrıştırabilecek bir uygulama yoktur . sonuçta ortaya çıkan yürütülebilir bayt kodu . Başka bir deyişle, Notepad.exe kadar basit bir şey alabilecek, küçük 190k dosyasını parçalayabilecek ve% 100'ü Linux veya OSX üzerinde çalışabilecek bir uygulamaya yeniden birleştirebilecek bir uygulama yoktur.

Sorunun adamının, Wine veya Parallels gibi programlar aracılığıyla yazılımı sanallaştırabilir veya uygulamaları çalıştırabilirsek, neden farklı sistemler için bayt kodunu yeniden çeviremediğimizi bilmek istedim. Bunun nedeni, bir uygulamayı başka bir mimari için tamamen yeniden birleştirmek istiyorsanız, yeniden birleştirmeden önce çalıştırmak için gereken tüm bayt kodunu ayrıştırmanız gerekir. Her uygulamada, örneğin bir Windows makinesi için exe dosyasından daha fazlası vardır. Tüm Windows uygulamaları, menüler, metin alanları, pencere yeniden boyutlandırma yöntemleri, ekrana çizim, OS mesajları gönderme / alma vb. Oluşturmak için düşük düzeyli Windows çekirdek nesnelerini ve işlevlerini kullanır ...

Uygulamaya yeniden birleştirmek ve farklı bir mimaride çalıştırmak için tüm bayt kodlarının sökülmesi gerekir.

Wine gibi uygulamalar Windows ikili dosyalarını bayt düzeyinde yorumlar. Çekirdeğe yapılan çağrıları tanır ve bu çağrıları ilgili Linux işlevlerine çevirir veya Windows ortamını taklit ederler. Ancak, bu bayt-bayt (veya opcode için opcode) yeniden çeviri değildir. Daha çok bir işlev-işlev çevirisidir ve bu biraz farklıdır.


Hiç teorik değil. Ve farklı işletim sistemlerinde diğer ikili dosyaları çalıştıran birçok uygulama vardır. Şarap duydun mu? Linux, Solaris, Mac OSX, BSD ve diğerleri gibi farklı işletim sistemlerinde Windows ikili dosyalarını çalıştırır.
Keltari

İşletim sistemlerindeki fark, birçok işletim sistemini çalıştırmak için bir hipervizör kullanarak (veya bir diğerini taklit eden bir sistemde Şarap gibi bir "katmanı çalıştırmak için) çoğu sistemde kolayca yapılabilir. AFAIK, tüm "modern" gömülü olmayan işlemciler "sanallaştırılabilir" dir, bu nedenle komut kümesi öykünmesi / çevirisi gerekmez.
Daniel R Hicks

0

Tüm uzmanların bu noktayı kaçırdığı görülüyor: 'Çeviri' karmaşık ama bilgisayar için çok uygun (akıllı değil, sadece labaratuar). Ancak çeviriden sonra programların işletim sistemi desteğine ihtiyacı vardır, örneğin: GetWindowVersion Linux'ta mevcut değildir. Bu normalde emülatör tarafından sağlanır (çok büyük). Böylece basit programları 'önceden çevirebilirsiniz' ama bağımsız çalışabilmek için büyük bir kütüphaneye bağlanmanız gerekiyor. Her pencerenin programlarının kendi kernel.dll + kullanıcı.dll + kabuk.dll ile geliyor görüntüleme ...


Sadece zahmetli değil, zeka gerektirir. Örneğin, sonucu atladığınız adresi belirleyen ve tek bir komut gibi görünen bir şeyin ortasında olabilecek bazı hesaplamalar gördüğünüzü varsayalım.
David Schwartz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.