Yerel kod, makine kodu ve montaj kodu arasındaki fark nedir?


106

.NET dilleri bağlamında makine kodu ve yerel kod konusunda kafam karıştı.

Onların arasındaki fark ne? Bunlar aynı mı?


3
Bu soruyla ilgili bir sorum var. Bu soru StackOverflow gereksiniminin kapsamına giriyor mu? afaik değil, ama aynı zamanda bu tür sorular çok yardımcı / bilgilendirici. Bu tür sorulara izin verilmediğini varsayarsak, bu tür soruları burada değilse nereye sormalıyız?
Yusuf Azad

Yanıtlar:


150

Terimler gerçekten biraz kafa karıştırıcı, çünkü bazen tutarsız olarak kullanılıyorlar.

Makine kodu: Bu en iyi tanımlanmış olanıdır. İşlemcinizin (asıl işi yapan fiziksel metal parçası) doğrudan anladığı ve yürüttüğü bayt kodu talimatlarını kullanan koddur. Makinenizin çalıştırabilmesi için diğer tüm kodların çevrilmesi veya makine koduna dönüştürülmesi gerekir.

Yerel kod: Bu terim bazen makine kodunun (yukarıya bakın) kastedildiği yerlerde kullanılır . Bununla birlikte, bazen yönetilmeyen kodu ifade etmek için de kullanılır (aşağıya bakın).

Yönetilmeyen kod ve yönetilen kod: Yönetilmeyen kod, doğrudan makine kodunda derlenen C veya C ++ gibi bir programlama dilinde yazılmış kodu ifade eder . C #, VB.NET, Java veya benzeri ile yazılan ve yazılımdaki bir işlemciyi "simüle eden" sanal bir ortamda (.NET veya JavaVM gibi) yürütülen yönetilen kodla tezat oluşturur . Temel fark, yönetilen kodun , çöp toplamayı kullanarak ve nesnelere yapılan başvuruları opak tutarak kaynakları (çoğunlukla bellek tahsisini) sizin için "yönetmesidir". Yönetilmeyen kodmanuel olarak bellek ayırmanızı ve ayırmanızı gerektiren, bazen bellek sızıntılarına (ayırmayı kaldırmayı unuttuğunuzda) ve bazen de bölümleme hatalarına (ayırmayı çok erken kaldırdığınızda) neden olan kod türüdür. Yönetilmeyen ayrıca genellikle boş işaretçi referans alma veya dizi sınırları taşması gibi yaygın hatalar için çalışma zamanı kontrollerinin olmadığı anlamına gelir.

Kesin konuşursak, Perl, Python, PHP ve Ruby gibi dinamik olarak yazılmış çoğu dil de yönetilen koddur . Ancak, genellikle bu şekilde tanımlanmazlar, bu da yönetilen kodun aslında gerçekten büyük, ciddi, ticari programlama ortamları (.NET ve Java) için bir pazarlama terimi olduğunu gösterir .

Assembly kodu: Bu terim genellikle insanların gerçekten bayt kodu yazmak istediklerinde yazdıkları kaynak kodu türünü ifade eder. Bir montajcı gerçek bayt koduna bu kaynak kodunu döner bir programdır. Bir derleyici değildir çünkü dönüşüm 1'e 1'dir. Bununla birlikte, terim ne tür bir bayt kodunun kullanıldığı konusunda belirsizdir: yönetilebilir veya yönetilmez olabilir. Yönetilmezse, ortaya çıkan bayt kodu makine kodudur . Yönetilirse, .NET gibi bir sanal ortam tarafından perde arkasında kullanılan bayt kodu ile sonuçlanır. Yönetilen kod (örn. C #, Java) bu özel bayt kodu dilinde derlenir; bu, .NET durumunda Ortak Ara Dil (CIL) ve Java'da Java bayt kodu olarak adlandırılır.. Genel programcının bu koda erişmesi veya doğrudan bu dilde yazması için genellikle çok az ihtiyaç vardır, ancak insanlar bunu yaptıklarında, onu bayt koduna dönüştürmek için bir derleyici kullandıkları için genellikle derleme kodu olarak adlandırırlar .


C ++, makine koduna derlenebilir, ancak çoğu zaman bir işletim sistemi ile çalışacak exe gibi diğer formatlarda derlenir.
Gordon Gustafson

Çöp toplamayı ve genellikle makine koduna göre derlenen opak referansları destekleyen diller vardır. Common Lisp'in çoğu ciddi uygulaması bunu yapar. Söyledikleriniz Microsoft tarafından desteklenen diller için doğru olabilir, ancak Visual Studio tarafından desteklenenden daha fazla derlenmiş dil vardır.
David Thornley

3
@CrazyJugglerDrummer: C ++ derleyicileri tarafından oluşturulan EXE dosyalarında bulunan kod hala makine kodudur. @David Thornley: Sadece bunlardan çok daha fazla dilden bahsetmiştim, ancak her belirsiz tuhaflıktan bahsederek işleri karmaşıklaştırmak istemedim.
Timwi

Bazı derleyiciler, birçoğu, aslında C / C ++ veya diğer dillerden derleme diline derler ve sonra assembler'ı çağırır ve derleyici, bunu çoğunlukla makine kodu olan ancak işlemcide belleğe girmeden önce birkaç dokunuşa ihtiyaç duyan nesne dosyalarına dönüştürür. bağlayıcı, hepsini programın makine kodu sürümüne bağlar. Nokta C / C ++, vb. Çoğu zaman doğrudan makine koduna derlenmez, kullanıcı tarafından görünmez yolda iki veya üç adım atar. Örneğin TCC, bunun bir istisnasıdır ve doğrudan makine koduna gider.
old_timer

Bu nitpicking gibi geliyor, ancak tüm derleyiciler 1-1'i işlem kodlarına çevirmiyor. Aslında, birçok modern derleyici, sınıflar gibi soyutlama yapılarını destekler. Örnek: TASM, Borland'ın montajcısı. en.wikipedia.org/wiki/TASM
Prime

45

Bir C # programında hata ayıklarken Debug + Windows + Disassembly kullandığınızda gördükleriniz, bu terimler için iyi bir kılavuzdur. JIT optimizasyonu etkinleştirilmiş Sürüm yapılandırmasında C # ile yazılmış bir 'merhaba dünya' programını derlediğimde bunun ek açıklamalı bir sürümü:

        static void Main(string[] args) {
            Console.WriteLine("Hello world");
00000000 55                push        ebp                           ; save stack frame pointer
00000001 8B EC             mov         ebp,esp                       ; setup current frame
00000003 E8 30 BE 03 6F    call        6F03BE38                      ; Console.Out property getter
00000008 8B C8             mov         ecx,eax                       ; setup "this"
0000000a 8B 15 88 20 BD 02 mov         edx,dword ptr ds:[02BD2088h]  ; arg = "Hello world"
00000010 8B 01             mov         eax,dword ptr [ecx]           ; TextWriter reference
00000012 FF 90 D8 00 00 00 call        dword ptr [eax+000000D8h]     ; TextWriter.WriteLine()
00000018 5D                pop         ebp                           ; restore stack frame pointer
        }
00000019 C3                ret                                       ; done, return

Benzer bir görüntü elde etmek için pencereye sağ tıklayın ve "Kod Baytlarını Göster" seçeneğini işaretleyin.

Soldaki sütun, makine kodu adresidir. Değeri hata ayıklayıcı tarafından taklit edilir, kod aslında başka bir yerde bulunur. Ancak bu, JIT derleyicisi tarafından seçilen konuma bağlı olarak herhangi bir yerde olabilir, bu nedenle hata ayıklayıcı, yöntemin başlangıcında adresleri 0'dan numaralandırmaya başlar.

İkinci sütun makine kodudur . CPU'nun yürüttüğü gerçek 1'ler ve 0'lar. Makine kodu, burada olduğu gibi, genellikle onaltılık olarak görüntülenir. Belki açıklayıcı, 0x8B'nin MOV komutunu seçmesidir, ek baytlar CPU'ya tam olarak neyin taşınması gerektiğini söylemek için vardır. Ayrıca CALL komutunun iki çeşidine dikkat edin, 0xE8 doğrudan çağrı, 0xFF dolaylı çağrı talimatıdır.

Üçüncü sütun, montaj kodudur . Assembly, makine kodu yazmayı kolaylaştırmak için tasarlanmış basit bir dildir. IL ile derlenen C # ile karşılaştırır. Derleme kodunu çevirmek için kullanılan derleyiciye "assembler" denir. Muhtemelen makinenizde Microsoft assembler'a sahipsiniz, yürütülebilir adı 64 bit sürüm için ml.exe, ml64.exe'dir. Kullanımda olan montaj dillerinin iki yaygın sürümü vardır. Gördüğünüz, Intel ve AMD'nin kullandığı. Açık kaynak dünyasında, AT&T gösteriminde derleme yaygındır. Dil sözdizimi, yazıldığı CPU türüne büyük ölçüde bağlıdır, bir PowerPC için montaj dili çok farklıdır.

Tamam, bu, sorunuzdaki iki terimi ele alıyor. "Yerel kod" belirsiz bir terimdir, nadiren yönetilmeyen bir dildeki kodu tanımlamak için kullanılmaz. Belki de öğretici, bir C derleyicisi tarafından ne tür bir makine kodu üretildiğini görmektir. Bu, C'deki 'merhaba dünya' versiyonudur:

int _tmain(int argc, _TCHAR* argv[])
{
00401010 55               push        ebp  
00401011 8B EC            mov         ebp,esp 
    printf("Hello world");
00401013 68 6C 6C 45 00   push        offset ___xt_z+128h (456C6Ch) 
00401018 E8 13 00 00 00   call        printf (401030h) 
0040101D 83 C4 04         add         esp,4 
    return 0;
00401020 33 C0            xor         eax,eax 
}
00401022 5D               pop         ebp  
00401023 C3               ret   

Çoğunlukla C # programı tarafından oluşturulan makine koduna çok benzediği için açıklama eklemedim . Printf () işlev çağrısı Console.WriteLine () çağrısından oldukça farklıdır ancak geri kalan her şey yaklaşık olarak aynıdır. Ayrıca, hata ayıklayıcının artık gerçek makine kodu adresini oluşturduğunu ve semboller konusunda biraz daha akıllı olduğunu unutmayın. Yönetilmeyen derleyiciler gibi makine kodu oluşturduktan sonra hata ayıklama bilgisi oluşturmanın bir yan etkisi de sıklıkla görülür. Makine kodunun benzer görünmesi için birkaç makine kodu optimizasyonu seçeneğini kapattığımı da belirtmeliyim. C / C ++ derleyicilerinin kodu optimize etmek için çok daha fazla zamanı vardır, sonucu yorumlamak genellikle zordur. Ve hata ayıklaması çok zor.

Buradaki kilit nokta , JIT derleyicisi tarafından yönetilen bir dilden üretilen makine kodu ile yerel bir kod derleyicisi tarafından üretilen makine kodu arasında çok az fark olmasıdır. C # dilinin yerel bir kod derleyiciyle rekabet edebilmesinin birincil nedeni budur. Aralarındaki tek gerçek fark, destek işlevi çağrılarıdır. Bunların çoğu CLR'de uygulanmaktadır. Ve bu, birincil olarak çöp toplayıcının etrafında döner.


6

Yerel kod ve makine kodu aynı şeydir - CPU'nun yürüttüğü gerçek baytlar.

Montaj kodunun iki anlamı vardır: Birincisi, daha insan tarafından okunabilir bir biçime çevrilen makine kodudur (komutlar için baytlar, "JMP" gibi (kodda başka bir noktaya "atlar") kısa kelimeye benzeyen anımsatıcılara çevrilmiştir. DLL veya EXE'de yaşayan IL bayt kodudur (C # veya VB gibi derleyicilerin oluşturduğu, sonunda makine koduna çevrilecek, ancak henüz değil) komut baytlarıdır.


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.