Makale Özeti

Bu makalede Microsoft Intermediate Language yani .NET mimarisindeki ara dilin yapısını inceleyeceğiz. ILDASM aracını kullanarak MSIL kodlarının içerisine bakacağız ve hata ayıklamada nasıl kullanacağımza değineceğiz.

Makale

Untitled Document

MSIL Yapısını İnceleyelim

Bu makalede Microsoft Intermediate Language yani .NET mimarisindeki ara dilin yapısını inceleyeceğiz. ILDASM aracını kullanarak MSIL kodlarının içerisine bakacağız ve hata ayıklamada nasıl kullanacağımza değineceğiz.

Giriş

.Net mimarisinin bize sağladığı birçok avantajdan bahsettik şimdiye kadar. Bunu nasıl yaptığını ise .Frameworku incelerken karşımıza bir katman olarak çıkan Common Language Runtime(CLR) bize inanılmaz bir avantaj sağlıyordu: birden fazla dili kullanma. Bu çok ciddi bir avantaj eğer Visual Basic biliyorsam Visual Basic .Net ile yazılım geliştirebilirim, eğer C# biliyorsam onunla, eğer Java biliyorsam J# ile. Bu diller saymakla bitmez demiştik; bugün itibariyle .Net platformunda 37 farklı dil destekleniyor. Bu farklı dil desteğini bize sağlayan ise ara dil mekanizmasıydı. Bu makalede Microsoft Intermedia Languageı yani MSILi inceliyor yapısının derinleklerine iniyor olacağız.

Gereksinimler

Bu makalede anlatılanları uygulayabilmeniz için öncelikle bilgisayarınızda .Net Framework yüklü olmalıdır. Örnek kodları C# dilinde yazdığım için temel düzeyde C# biliyor olmanız gerekmektedir. Makalenin ilerleyen kısımlarında değineceğimiz Ildasm aracını ve C# derleyicisini kullanacağımız için bu konularda da temel bilgiye sahip olmak gerekmektedir.

MSILe Genel Bakış

MSIL yani Microsoft Intermediate Language bir ara dildir, yazmış olduğunuz kodlar ilk defa derleme anında bu ara dile dönüştürülür. MSIL CPUdan bağımsızdır ve stack-tabanlı bir bilgi olduğu için rahatlıkla bulunduğu platforma özel native koda dönüştürülebilir. MSIL yorumlanmaz(interpret), derlenir(compile). Varolan Just-In-Time(JIT) derleyici ara dil kodunu native koda dönüştüren bir görev üstlenir. Bu stack tabanlı kod sayesinde farklı platformlar arası taşınabilme özelliği ortaya çıkmaktadır. Biraz kafanız karışabilir ama zaten bu makale de bu işlemlerin nasıl olduğunu, arka planda neler yapıldığını ve ara dil kodunda neler olduğunu anlayabilmemiz için yazıldı.

Son bir özet çıkaracak olursak: MSIL nesneye yönelik programlamayı destekler; .Net Framework içerisindeki veri tipleri ile çalışır(System.String, System.Int32 gibi); Yönergeler(instructions) birçok tip olarak sınıflandırılabilir: loading(ld*) yani yükleme, aritmetik işlemler, mantıksal ifadeler, bellek ayırımı, hata yakalama, storing(st*) yani saklama gibi. İsterseniz genel bakışı burada bitirelim ve incelemeye başlayalım MSILi.

MSILi İnceleyelim

Hemen bir örnek kod ile başlayalım, basit bir C# kodu ile "Merhaba Dünya" diyelim ve ardından onun nasıl ara dile derlendiğini inceleyelim:

Console.WriteLine ("Merhaba Dunya")

Az sonra anlatacağımız Ildasm aracı ile oluşacak ara dil kodunu açacak olursak:

// ildasm aracı ile dissamble edilmiş kod
ldstr "Merhaba Dunya"
call void [mscorlib]System.Console::WriteLine(string)

Şimdi de bunların ne anlama geldiğini inceleyelim:

ldstr açılımına baktığımızda load string yönergesi var; "Merhaba Dunya" ifadesini stack içerisine yüklüyoruz. Call yaptığımız bir metodu çağırdığımızın ifadesi; console sınıfına ait WriteLine methodunu çağıyor. [mscorlib] ifadesi ise bu metodu barındıran dll dosyanın adı yani mscorlib.dll. Son olarak System ifadesi de console sınıfını içeren isim uzayı(namespace).

Görüldüğü aslında IL kodu çok karışık birşeyler içermiyor, eğer basitçe bir assembly dilinin ne yaptığı konusunda bilgi sahibi iseniz sizin için MSILi öğrenmek de çok kolay olacaktır.

Şimdi biraz daha detaylı bir örnek görelim, içerisinde aritmetik işlemler olan bir C# kodu yazalım:

// C# program kodu
int i = 10;
if(i!=20)
i = i*20;
Console.WriteLine(i);

Ildasm aracı ile dissamble ettiğimizde karşımıza gelecek kaynak kodu:

// ildasm aracı ile dissamble edilmiş kod
IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.s 20
IL_0006: beq.s IL_000d
IL_0008: ldloc.0
IL_0009: ldc.i4.s 20
IL_000b: mul
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: call void [mscorlib]System.Console::WriteLine(int32)

Kısa bir C# kodu ne hale geldi diyeceksiniz, satır satır inceleyelim. İncelemeye geçmeden IL_ ile başlayan satır ifadeleri okumamızı kolaylaştıracaktır.

ldc.i4.s ifadesinin karşılığı şu; ldc yani load constant , i4 yani four byte integer, s yani single byte argument. Elimizdeki 10 sabitini stackin içerisine yerleştiriyoruz, bunu yaparken tipini de tanımlıyoruz.

stloc.0 ifadesinin karşılığı şu; stloc yani store in location, 0 yani sıfırıncı değişken (zeroth variable). 10 sabitini stack içerisinden alıp değişken numarası 0 olan bir değişken içerisinde tutuyoruz.

ldloc.0 ifadesinin karşılığı şu; ldloc yani load from location, 0 yani sıfırıncı değişken(zeroth variable). Sıfırıncı değişkenden gerekli değer okunur ve stack üzerine eklenir.

ldc.i4.s ifadesinin karşılığı şu; ldc yani load constant, i4 yani four byte integer, s yani single byte argument. Integer sabiti olarak 20yi stacke ekler.

beq.s ifadesinin karşılığı şu; beq yani branch of equal to, s yani single byte argument. Stack içerisinde iki değeri alır ve karşılaştırır, eğer eşitlerse verilen IL_ ifadesine geçiş yapılır.

ldloc.0 i değişkenini stacke ekler.

ldc.i4.s integer sabiti 0ı stacke ekler.

mul yani multiply stackde yer alan iki sayıyı alır ve birbiri ile çarpar. Sonucu yine stacke geri yollar, dönen çarpım sonucu stack içerisinde en üstte yer alacaktır.

stloc.0 stack içerisinde en üstte yeralan ifadeyi alır, bu durumda çarpım sonucu olmaktadır. Bu değeri i değişkeninin içine atar.

ldloc.0 elimizdeki i değişkenin içeriğini stack içerisine yazar.

call yani metodun çağırılması işlemi gerçekleşir. Az önceki örnekte olduğu gibi WriteLine metodu çağırılmaktadır. [mscorlib] ifadesi ise bu metodu barındıran dll dosyanın adı yani mscorlib.dll. Son olarak System ifadesi de console sınıfını içeren isim uzayı(namespace). Sonuç ekrana görüntülenecektir.

ILDASM ile Hata Ayıklama

Microsoft .NET Framework SDK içerisinden bir disassembler aracı da çıkmaktadır. Disassembler dediğimiz varolan assemblylerin içeriğini ortaya çıkarmasından gelmektedir. Bu IL disassemblerın adı Ildasm.exe dir. Konum olarak [Sürücünüz]\Program Files\Microsoft.Net\FrameworkSDK\Bin klasörünün altındadır. Ildasm assembly dediğimiz .NET nesnelerini yükleyerek, MSIL kodunu ve diğer bilgileri bize göstermektedir.

Örnek Ekran Görüntüsü:

ILDASM aracı ile uygulamalarınızda hata ayıklarken ciddi anlamda yararlanabilirsiniz, ama tabiki MSIL kodu üzerine oldukça iyi seviyede bilgi sahibi olmanız gerekmektedir.

 

İsterseniz bu yazıyı burada bitirelim ve bundan sonraki yazımızda ILDASM ile hatalı yazmış olduğumuz bir C# programının MSIL kodunda hata ayıklayalım.

 

Mehmet Nuri ÇANKAYA

cankaya@aspnedir.com