2014-10-12 30 views
15

Eğitim amaçlı olarak, bir parça IL öğreniyorum (esas olarak, kaputun altında “%” ye ne olduğunu merak ettiğim için (ki bu, rem olarak ortaya çıktı) ve kazmaya başladı ...). ldc.i4.1 sonraBu durumda 'br.s' IL opcode neden kullanılıyor?

.method public hidebysig static bool ReturnTrue() cil managed 
{ 
    // Code size  7 (0x7) 
    .maxstack 1 
    .locals init ([0] bool CS$1$0000) 
    IL_0000: nop 
    IL_0001: ldc.i4.1 
    IL_0002: stloc.0 
    IL_0003: br.s  IL_0005 
    IL_0005: ldloc.0 
    IL_0006: ret 
} // End of method Primes::ReturnTrue 

yığını ve stloc üzerinde 1 iter:

Sadece biraz şeyler yıkmak doğru döndüren ve 'gn' işlem kodu merak ediyordum, bir yöntem yazdı .0 bunu 0'ıncu lokasyona yerleştirir, br.s temel olarak (bildiğim kadarıyla) IL_0005 satırında ldloc.0'a 'goto' yapar. Neden bu

mı? Neden hiç bir IL_0004 hattı yok ki bu yüzden bu ihmal edilebilir?

+6

Hiçbir IL_0004 yoktur, çünkü 'br.s' iki bayttır. Sanırım optimizasyonları devre dışı bıraktın mı? Evet, o zaman garip şeyler beklersin. Optimizasyonları açtığınızda ne elde edersiniz? – hvd

+1

Ardından '1'i yığına iter ve hemen geri döner. IL_0000: ldc.i4.1 IL_0001: yöntemi başlangıcından itibaren bayt öğretim ofset olduğu xxxx "IL_xxxx" de ret – Apeiron

+0

. br.s, atlamak için hedef komut olan tek bir bayt işleneni alan bir tek bayt komutudur (geri kalanı gibi). –

cevap

13

dal hata giderme amacıyla kendisine, dönüş değeri hesaplanır ve toplanabilir ve hemen ayıklayıcı "olarak adlandırılan" olabilir edilmiştir. Yöntem girişinde NOP ile aynıdır. @hvd devlet olarak IL_0004 ile ilgili olarak

, br.s bir adresi var ve sana hitap ne kadar tanıdık bilmiyorum ("tek satır", burada bir bayt sığmayan, ancak bir talimat genellikle bir bayt, yani 8-bit, adres ya da ofset, tipik olarak 8-, 16 ya da 32-bit. Bu durumda, 8-bit'lik bir ofset ile 8-bit'lik bir ofset var. Wikipedia has a good article on CIL-OP-codes).

Ayrıca, en hepsi bu kadar tek kesme noktası işlevi dönüşünde tabi senin olayda, sonuna kadar IL_0005 atlamak, senin yöntem if -branches birden döner vardır ve örneğin aracılığıyla diyelim.

+0

Huh? Bu, br.s'ın işleneni için yalnızca bir bayt olan baytların sayısıdır ve bir adres genellikle bir bayta sığmaz. 'Br.s' bir adres değil, 8 bitlik bir göreli ofset alır. – hvd

+0

@hvd Haklısınız, her zaman IL adreslemenin bayt tabanlı değil, kelime uzunluğuna bağlı olduğunu varsaydım, ama siz doğruyunuz;) – flindeberg

3

Bu C# derleyicisi kullanan biri gibi, bir recursive-descent parser çok yaygın eserdir. Bu dallardan kurtulmak için bir peephole optimizer gerekir.

derleyici, sonucu derleme zamanında tespit edilebilir önemsiz bir işlem optimum olduğunda ortaya olasılığı. C# derleyicisinin bir gözetleme deliği iyileştiricisi yoktur, çünkü gerekli değildir, bu gereksiz dalları ortadan kaldırır. Optimizörü jitter'e koymak genelde kazanan bir stratejidir, her dil derleyicisi bundan yararlanır. Derleyicileri çok basit tutar ve bir kod iyileştiricisini yazmanın ve sürdürmenin önemli bir masrafını sadece bir (veya birkaç) yerde tutar. seğirme iyileştirici bittiği yerde değil

, tüm yöntem zamanında ortadan kaybolacak. Yöntemi geri çağıran kodun, derleme zamanında bilinmesi nedeniyle, yöntemi çağırdığı kodun büyük ölçüde optimize edileceği yüksek bir olasılıkla. MSIL bu tür görünce aksi takdirde kod kolayca basitleştirilmiş veya bir hata :)

0

O Visual Studio 2013 tarihinde şey olmayacak vardır edilebileceği güçlü bir ipucu, bu dev nihayet sabit gibi görünüyor. VS2013'de böyle görünecek.

.method public hidebysig static bool ReturnTrue() cil managed 
{ 
    .maxstack 1 
    ldc.i4.1 
    ret 
} // End of method Primes::ReturnTrue 
+1

'Debug' flag setiyle derlemeyi deneyin. – flindeberg

İlgili konular