Hassas durumlarda, switch()'in aralıklı (case X: .. case Y:) kullanımından uzak durun!
Şöyle bir test kodumuz var:
import core.stdc.stdio: printf;
void main() {
char harf = 64; // Octal 0x100; @ işareti ve devamında A var
while(harf) {
harf++;
//* toggle-code on
if(harf > 64 && harf < 91) {
printf("Büyük Harf: %c\n", harf);
} else if(harf > 96 && harf < 123) {
printf("Küçük Harf: %c\n", harf);
}/*/
switch(harf) {
case 'A': .. case 'Z':
printf("Büyük Harf: %c\n", harf);
break;
case 'a': .. case 'z':
printf("Küçük Harf: %c\n", harf);
break;
default:
}//*/
}
}
İlk durum (toggle-code off) yani baştaki kod öbeğini (snippet) derlediğinizde iki koşul ifadesinden biri şartı sağladığında ekrana Büyük veya Küçük harfleri yazmakta. Aynı işi ikinci durum (toggle-code on) da yapmakta ama diğerinden daha uzun süren bir yöntemle:
Look-up Table
Önce tüm olasılıkları (27*2+1) assembly'deki .rodata bölümüne (segment) dizge olarak yerleştiriyor. Bunu, yanıdaki "Büyük, Küçük, Harf ve %c" ifadelerinden anlıyoruz. Çünkü bu veriler de program işletilirken ekrana yazılmak üzere kullanılıyor. Sonra ana döngüden bağımsız başka bir döngü içinde ve her seferinde bunu tekrar ederek tüm olasılıkları karşılaştırıyor.
Ölme eşeğim ölme...:)
Tabi switch() case'in bu kullanımı bir kolaylık. Sizi fazla düşündürtmeden amacınıza hızlı bir şekilde ulaşmanızı sağlıyor. Hatta, bunun if() gibi ayrı bir komut olmadığını, derleyicinin kafasına göre if() ve koşul verilerinden oluşan bir öbek (snippet) meydana getirdiği sonucunu pekala çıkartabiliriz. O yüzden dikkatli kullanmakta fayda görüyorum. Hatta !!!
Evet, hatta...:)
Örneğin ilk bölümünde if()'leri ayrı ayrı kullanmayın! Eğer birbirleriyle ilintiliyse mutlaka else if() şeklinde devam edin. Çünkü bu ikisi arasında çok küçük (tek satır!) ama büyük olabilecek bir fark var! O da her iki assembly öbeği arasına bir dallanma satırı ('jmp short LC') eklemesi!
Buradaki LC ilk if() ifadesi. Oysa else if() ile ikinci ifadeyi yazsaydık bu satır olmayacaktı. Olmadığında da 1.'yi denetledikten sonra ikinciye bakması (zaten biz bunu istiyoruz!) hem de dolanmadan. Çünkü bahsettiğim ek dallanma satırı olunca ilk ifadeyi kontrol ettikten sonra tekrar kendi içine dönüyor ve oradaki bir kaç satırı işlettikten sonra ikinci ifadenin (L35) başına dallanıyor.
'(Yaş 35, yolun yarısı edermiş, kelaka...:))'
İşte assembly kodu:
'_Dmain:
push EBP
mov EBP,ESP
sub ESP,4
push EBX
push ESI
mov byte ptr -4[EBP],040h
LC:
cmp byte ptr -4[EBP],0
je L57
inc byte ptr -4[EBP]
mov AL,-4[EBP]
cmp AL,040h
jbe L35
cmp AL,05Bh
jae L35
movzx ECX,byte ptr -4[EBP]
push ECX
mov EDX,offset FLAT:.rodata[026h]@SYM32
push EDX
call printf@PC32
add ESP,8
' jmp short LC'
L35:
mov BL,-4[EBP]
cmp BL,060h
jbe LC
cmp BL,07Bh
jae LC
movzx ESI,byte ptr -4[EBP]
push ESI
mov EAX,offset FLAT:.rodata[05Ch]@SYM32
push EAX
call printf@PC32
add ESP,8
jmp short LC
L57:
xor EAX,EAX
pop ESI
pop EBX
leave
ret'
Dip Not: Örnekte özellikle std.stdio; sınfını kullanmadım çünkü assembly kodu iyice karışıyor. Hata bulmak için yapacağınız bu tür denemelerde mümkünse writefln() gibi komutları alias ile gölgeleyin. Yani printf() işlevine yönlendirin....
Başarılar...
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]