.NET dilleri bağlamında makine kodu ve yerel kod konusunda kafam karıştı.
Onların arasındaki fark ne? Bunlar aynı mı?
.NET dilleri bağlamında makine kodu ve yerel kod konusunda kafam karıştı.
Onların arasındaki fark ne? Bunlar aynı mı?
Yanıtlar:
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 .
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.
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.
.NET'te, derlemeler MS Intermediate Language kodunu (MSIL, bazen CIL) içerir.
'Yüksek seviyeli' bir makine kodu gibidir.
MSIL yüklendiğinde, JIT derleyicisi tarafından yerel koda (Intel x86 veya x64 makine kodu) derlenir .