Derleyici yazarların aslında makine kodunu 'anlamaları' gerekir mi? [kapalı]


10

Biraz tuhaf bir soru olabilir.

C ++ derleyicisi (veya VM olmayan herhangi bir dil) yazan bir adam: Ham makine dilini okuyabilmesi / yazabilmesi gerekiyor mu? Bu nasıl çalışıyor?

EDIT: Ben özellikle başka bir programlama dili için değil, makine kodu derleyen derleyicileri kastediyorum.



1
Hayır. Bunu bilmenize bile gerek yok, sadece körü körüne, dikkatsizce
SK-logic

1
Coffescript javascript derler .
Kartik

@Kartik Javascript için derleyen CoffeeScript derleyicisi, ayrıca herhangi bir Javascript için derlenen bir Javascript derleyicisi içeriyor mu? Yoksa sadece Javascript kaynak kodu için derleniyor ve başka bir şey değil mi?
Aviv Cohn

Coffeescript derleyicisi sadece cofeescript'i javascript'e çevirir. Javascript derlenmemiştir, tarayıcı tarafından işlenir. Bir dili diğerine derleyen bir derleyici yazabileceğinizi söylemek istedim, bunun için makine dilini bilmek zorunda değilsiniz. Başka bir örnek, Shakespeare'in C ++ 'da oynadığı' SPL 'derleyicisidir. shakespearelang.sourceforge.net
Kartik

Yanıtlar:


15

Hayır, hiç de değil. Derleyicinizin bunun yerine montaj kodu vermesi (hatta çoğu zaman tercih edilir) mümkündür. Montajcı daha sonra gerçek makine kodunu oluşturmaya özen gösterir.

Bu arada, VM dışı uygulama ile VM uygulama arasındaki ayrımınız yararlı değildir.

  • Yeni başlayanlar için, bir VM kullanmak veya makine koduna önceden derleme yapmak, bir dili uygulamak için sadece farklı yollardır; çoğu durumda bir dil her iki strateji kullanılarak da uygulanabilir. Aslında bir kez C ++ tercümanı kullanmak zorunda kaldım .

  • Ayrıca, JVM gibi birçok VM'nin her ikisi de sıradan bir mimari gibi ikili bir makine kodu ve bazı montajcıları vardır.

(Clang derleyicileri tarafından kullanılan) LLVM burada özel bir sözü hak etmektedir: Talimatların bayt kodu, metin montajı veya bir derleyiciden yayılmasını çok kolaylaştıran bir veri yapısı olarak temsil edilebileceği bir VM tanımlar. Bu nedenle, hata ayıklama için (ve ne yaptığınızı anlamak için) yararlı olsa da, montaj dilini, hatta yalnızca LLVM API'sını bilmek zorunda kalmazsınız.

LLVM ile ilgili güzel olan şey, VM'sinin sadece bir soyutlama olması ve bayt kodunun genellikle yorumlanmaması, bunun yerine şeffaf bir şekilde JITted olmasıdır. Bu nedenle, CPU'nuzun talimat setini bilmek zorunda kalmadan, etkili bir şekilde derlenmiş bir dil yazmak tamamen mümkündür.


Ve LLVM'nin bir başka güzel özelliği, etkin bir arka uç uygulamak için hedef ISA'yı derinlemesine anlamaya gerek olmamasıdır. Oldukça açıklayıcıdır, bu yüzden neredeyse bir ISA belirtimini kopyalamaya ve yapıştırmaya çalışmadan .td dosyalarına yapıştırabilirsiniz.
SK-logic

Cevabın için teşekkür ederim. Soru: Derleyicinizin yazarının makine kodunu anlamak zorunda olmadığını, yanıtınızın ve diğerlerinin yanıtlarından anlıyorum, kendisi için makineye gerçek dönüştürme kodunu yapan başka bir araç kullanabilir. Ancak, bu aracı yazan adam yoktu , hakkını makine dilini anlamak zorunda? Bir dilden makine koduna gerçek dönüşümü yapan yazılımı yazan adam aslında makine dilini anlamalı mı?
Aviv Cohn

5
@Prog evet. Bir soyutlama katmanı oluşturursanız, yalnızca altındaki katmanı anlamanız gerekir. Tüm katmanları temel olarak anlamak yararlı olsa da, bu gerçekten gerekli değildir. Bir transistör kullanmak için kuantum fiziğini anlamanız gerekmez. CPU kullanmak için çip tasarımını anlamanız gerekmez. Montaj yazmak için makine kodunu bilmenize gerek yoktur. Bir VM, vb. Kullanırken platformun talimat setini bilmenize gerek yoktur. Ancak birisi bu soyutlama seviyelerini sizinkinin altına inşa etmek zorunda kaldı.
amon

1
@ SK-logic Duyduğumdan doğru değil (en azından iyi kod istiyorsanız). Llvm için Aarch64 arka ucunu uygulayan insanlar oldukça az zorluk yaşadı (biri için tehcir, yük deposu modelleri korkunç, ..). Ve bu görmezden var odasında büyük fil: ISA bellek modeli ve dil size bellek modeli sizsiniz, ilgilenen içinde bir derleyici üzerinde çalışmak, ancak yapabilirsiniz mimarisini anlamadan bir arka uçta değil iş ...
Voo

1
Kavramsal olarak montaj ve makine kodu arasında gerçekten önemli bir fark olmadığını da ekleyeceğim. Bir kez belirli bir talimatın nasıl kullanılacağını, bu talimatın opcode'unun ne olduğunu bilerek çok fazla fayda sağlayamazsınız. MOV'u nasıl kullanacağınızı biliyorsanız, 27 numaralı talimatın ne olduğunu bilmiyorsanız gerçekten önemli değil, bence @ SK-logic'in tanımladığı şeye benziyor.
whatsisname

9

Hayır. Sorunuzun kilit noktası derlemenin son derece geniş bir terim olmasıdır. Derleme herhangi bir dilden herhangi bir dile olabilir. Montaj / makine kodu, derleme hedefi için birçok dilden sadece biridir. Örneğin, C #, F # ve VB.NET gibi Java ve .NET dillerinin tümü, makineye özgü kod yerine bir tür ara kodla derlenir. Daha sonra VM'de çalışıp çalışmadığı önemli değil, dil hala derleniyor. C gibi başka bir dile derleme seçeneği de var. C aslında oldukça popüler bir derleme hedefi ve birçok araç bunu yapıyor. Ve son olarak, sizin için makine kodu üretmenin zor işini yapmak için bazı araç veya kütüphane kullanabilirsiniz. örneğin , bağımsız bir derleyici oluşturmak için gereken çabayı azaltabilecek LLVM vardır.

Ayrıca, düzenlemenizin bir anlamı yoktur. "Her mühendisin motorun nasıl çalıştığını anlaması gerekir mi? Ve ben de motorlarda çalışan mühendisleri soruyorum." Bir makine kodu yayan bir program veya kütüphane üzerinde çalışıyorsanız, bunu anlamanız gerekir. Mesele şu ki, derleyici yazarken böyle bir şey yapmak zorunda değilsiniz. Birçok kişi bunu senden önce yaptı, bu yüzden tekrar yapmak için ciddi bir nedene ihtiyacın var.


Makine dilini fiilen dönüştüren aracı veya kütüphaneyi yazan kişinin makine dilini tamamen anlaması gerekiyor, değil mi?
Aviv Cohn

3
@Prog Programlamak için bir programlama dilini tam olarak anlamanız gerekiyor mu? Hayır, ancak muhtemelen en uygun olmayan kodu yazacaksınız ve başkalarının yapabileceği belirli şeyleri yapamazsınız. Buna çeviren bir derleyici yazarsanız, makine dilini tamamen anlamanız gerekir mi? Hayır, ancak derleyiciniz yetersiz ve belirli şeyler yapamaz.
Sumurai8

@ Sumurai8: Her şeyi sizden daha iyi anlayan bir makine kodu yayıcısı yazmak için bir dereceye kadar makine dilini parça parça "anlayabilirsiniz". Örneğin, iyi bir çerçeve yazarsanız, her bir opcode'un tanımını maliyetleriyle ve boru hattıyla ilgili hususlarla birlikte yapılandırabilirsiniz ve ardından belirli bir makineyi optimize etme konusunda herhangi bir uzmanlığınız olmasa da çerçeveniz optimize edilmiş makine kodu yazabilir. Bu makine kodunu yetkin bir şekilde programlayabilmeniz muhtemelen zarar görmez.
Steve Jessop

@SteveJessop Her bir opcode'u, bir makineyi daha yüksek seviyeli bir kavramı ifade etmek için diğer opcodes ile birlikte nasıl zincirleyeceğinizi öğrenebileceğiniz bir noktaya kadar anlarsanız, makine dilini tamamen anlarsınız. O zaman orada her sorun için en uygun çözümü bulmak için çok tembelsiniz ;-)
Sumurai8

@ Sumurai8: hmm, ama en azından prensip olarak, her bir opcode'u yapılandırmam için gereken beş dakika boyunca kısaca "anlayabilir" ve sonra bir sonraki işlemden sonra opcode'u "anladığım" zamana kadar unutmuş olabilirim. Muhtemelen "ham makine dilini okuyabilme / yazabilme" ile soru soran bu değildir. Tabii ki burada oldukça darn iyi bir çerçeve olduğunu varsayıyorum, bu talimat setinin her bir opcode'u hakkında tüm yararlı bilgileri tanımlamak ve kullanmak için yeterince yapılandırılabilir. LLVM bunu biraz hedefliyor, ancak "Voo" ya göre (aşağıdaki yorumda) buna çarpmadı.
Steve Jessop

3

Klasik olarak bir derleyicinin üç bölümü vardır: sözcüksel analiz, ayrıştırma ve kod oluşturma. Sözcük analizi, programın metnini dil anahtar sözcüklerine, adlarına ve değerlerine ayırır. Ayrıştırma, sözcüksel çözümlemeden gelen belirteçlerin dil için sözdizimsel olarak doğru ifadelerde nasıl birleştirildiğini gösterir. Kod üretimi, ayrıştırıcı tarafından üretilen veri yapılarını alır ve bunları makine koduna veya başka bir temsile çevirir. Günümüzde sözcüksel analiz ve ayrıştırma tek bir adımda birleştirilebilir.

Açıkça, kod üretecini yazan kişi, hedef makine kodunu, talimat setleri, işlemci boru hatları ve önbellek davranışı da dahil olmak üzere çok derin bir düzeyde anlamalıdır. Aksi takdirde derleyici tarafından üretilen programlar yavaş ve verimsiz olacaktır. Sekizli veya onaltılık sayılarla temsil edilen makine kodunu çok iyi okuyabilir ve yazabilirler, ancak genellikle makine kodlarını oluşturmak için dahili olarak makine kodunu oluşturmak için işlevler yazarlar. Teorik olarak, lexer ve ayrıştırıcıyı yazan kişiler makine kodunun oluşturulması hakkında hiçbir şey bilmeyebilir. Aslında, bazı modern derleyiciler, lexer ve ayrıştırıcı yazarların hiç duymadığı bazı CPU için makine kodu yayabilecek kendi kod oluşturma rutinlerinizi takmanıza izin verir.

Bununla birlikte, pratikte her adımdaki derleyici yazarları farklı işlemci mimarileri hakkında çok şey bilir ve bu da kod oluşturma adımının ihtiyaç duyacağı veri yapılarını tasarlamalarına yardımcı olur.


2

Uzun zaman önce iki farklı kabuk betiği arasında dönüştürme yapan bir derleyici yazdım. Makine kodunun yanına gitmedi.

Derleyici yazma çıktılarını anlamak zorundadır , ancak bu genellikle makine kodu değildir.

Çoğu programcı asla makine kodu veya montaj kodu üreten bir derleyici yazmaz, ancak özel derleyiciler diğer çıktıları üretmek için birçok projede çok yararlı olabilir.

YACC, makine kodunu vermeyen böyle bir derleyicidir….


0

Giriş ve çıkış dillerinizin anlambilimiyle ilgili ayrıntılı bir bilgi ile başlamanız gerekmez , ancak her ikisinin de zarif ayrıntılı bilgisiyle bitirmeniz daha iyi olur , aksi takdirde derleyiciniz alışılmadık bir şekilde buggy olacaktır. Dolayısıyla, girdiniz C ++ ve çıktınız belirli bir makine dili ise, sonunda her ikisinin de anlamını bilmeniz gerekir.

İşte makine koduna C ++ derlemedeki bazı incelikler: (sadece başımın üstünde, unuttuğumdan daha fazlası olduğundan eminim.)

  1. Hangi boyutta olacak int? Buradaki "doğru" seçim, hem makinenin doğal işaretçi boyutuna, hem de çeşitli boyutlardaki aritmetik işlemler için ALU'nun performansına ve mevcut derleyiciler tarafından makine için yapılan seçimlere dayanan bir sanattır. Makinede 64 bit aritmetik var mı? Değilse, 32-bit tamsayıların eklenmesi bir talimata, 64-bit tamsayıların eklenmesi ise 64-bit tamsayı eklemek için bir işlev çağrısına dönüşmelidir. Makinede 8 bit ve 16 bit ekleme işlemleri var mı veya 32 bit ops ve maskeleme olanları simüle etmeniz mi gerekiyor (örn. DEC Alpha 21064)?

  2. Makinedeki diğer derleyiciler, kütüphaneler ve diller tarafından kullanılan çağrı kuralı nedir? Parametreler yığını sağdan sola mı yoksa soldan sağa mı itiyor? Bazı parametreler kayıtlara giderken diğerleri yığına gider mi? Ints ve float farklı kayıt alanlarında mı? Kayıt tahsis edilen parametrelerin varargs çağrılarında özel olarak ele alınması gerekiyor mu? Hangi kayıtlar arayan kaydedilir, hangileri arayan kaydedilir? Yaprak arama optimizasyonları yapabilir misiniz?

  3. Makinenin vites değiştirme talimatlarının her biri ne işe yarar? 64 bit tamsayıyı 65 bit kaydırmak isterseniz sonuç ne olur? (Birçok makinede sonuç 1 bit kaydırma ile aynıdır, diğerlerinde ise sonuç "0" dır.)

  4. Makinenin bellek tutarlılık semantiği nedir? C ++ 11, bazı durumlarda bazı optimizasyonlara kısıtlamalar getiren, ancak diğer durumlarda optimizasyonlara izin veren çok iyi tanımlanmış bir bellek semantiğine sahiptir. İyi tanımlanmış bellek anlambilimine sahip olmayan bir dil derliyorsanız (C + + 11'den önceki her C / C ++ sürümü ve diğer birçok zorunlu dil gibi), devam ederken bellek anlambilimini icat etmeniz gerekir ve genellikle makine semantiğinize en uygun bellek semantiğini icat etmek isteyeceksiniz.

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.