- "asm" ve register belirteci "r"
- 
            İlk önce 'r' belirtecinin "asm" de kullanılışına bir bakalım.
            Örneğimiz GCC'nin nasıl yazmaç ayırdığını ve değerleri nasıl
            güncelleştirdiğini göstermektedir.
             - 
int main(void)
{
        int x = 10, y;
        asm ("movl %1, %%eax;
             "movl %%eax, %0;"
                :"=r"(y)        /* y çıktı terimidir */
                :"r"(x)         /* x girdi terimidir */
                :"%eax");       /* %eax geri dönen yazmaç */
}
- 
            Bu örnekte x'in değeri "asm" içinde y'ye kopyalandı. x ve y "asm"den
            yazmaçların içinde geçtiler. Bunun için üretilecek Sembolik Makina Dili
            kodu şuna benzer:
             - 
    main:
        pushl %ebp
        movl %esp,%ebp
        subl $8,%esp
        movl $10,-4(%ebp)
        movl -4(%ebp),%edx      /* x=10 %edx te tutulur */
#APP    /* asm burada başlıyor */
        movl %edx, %eax         /* x %eax e taşınır*/
        movl %eax, %edx         /* y edx e taşınır ve güncelleştirilir */
#NO_APP /* asm burada bitiyor */
        movl %edx,-8(%ebp)      /* y nin yığıttaki değeri %edx in değeri ile
                                   güncelleştirilir.*/
- 
           'r' belirteci kullanıldığında GCC herhangi bir yazmacı ayırmakta serbesttir.
            Örneğimizde x'i tutmak için %edx'i
            seçmiştir. x'in değerini %edx'ten
            okuduktan sonra y için yine %edx'i
            seçmiştir.
             - 
              y'nin değeri çıktı terimi bölümünde oldukça
              %edx'in güncelleştirilen değeri
              ;y'nin yığıttaki yeri, -8(%ebp)'de
              belirtilir. Eğer y girdi bölümünde tanımlanmış olsa
              idi, geçici y yazmacı (%edx) güncelleştirilmesine
              rağmen y'nin yığıttaki yeri güncelleştirilmezdi.
             - 
              %eax geri dönen yazmaçlar listesinde oldukça GCC onu
              bilgi tutmak dışında kullanmayacaktır.
             - 
              Çıktılar oluşmadan önce girdilerin yok olduğu farz edilerek, hem
              x girdisi hem y çıktısı aynı
              %edx yazmacında tutuldular. Ama şunu unutmayın eğer
              bir kaç komut işletecekseniz bunu yapamazsınız. Girdi ve çıktıların
              farklı yazmaçlarda tutulduğundan emin olmak için, & belirteç
              değiştiricisini kullanabiliriz.
             - 
              Bununla ilgili bir örnek :
             - 
        int main(void)
{
        int x = 10, y;
        asm ("movl %1, %%eax;
             "movl %%eax, %0;"
                :"=&r"(y)       /* y çıktı terimidir ve
                                   & belirteç değiştiricisidir. */
                :"r"(x)         /* x girdi terimidir */
                :"%eax");       /* %eax geri dönen yazmaçtır*/
}
- 
              Ve burada bu örnek için üretilmiş Sembolik Makina Dili kodunu
              bulabilirsiniz, x ve y'nin
              "asm" de farklı yazmaçta tutulduğu görülmektedir.
             - 
    main:
        pushl %ebp
        movl %esp,%ebp
        subl $8,%esp
        movl $10,-4(%ebp)
        movl -4(%ebp),%ecx      /* x, girdi %ecx tedir */
#APP
        movl %ecx, %eax
        movl %eax, %edx         /* y, çıktı %edx tedir */
#NO_APP
        movl %edx,-8(%ebp)
- Özel yazmaç belirteçlerinin kullanımı
- 
            Şimdi kişisel yazmaçları terimler için belirteç olarak kullanmaya bir
            bakalım. Aşağıdaki örneğimizde cpuid komutu girdiyi
            %eax yazmacından alıyor ve çıktıyı dört yazmaca
            veriyor: %eax, %ebx,
            %ecx, %edx. cpuid
            girdisi, op değişkeni, "asm"ye
            %eax cpuid'nin de beklediği gibi yazmacından giriyor.
            a, b, c ve
            d belirteçleri çıktıda dört yazmaçtaki değerleri
            kendilerinde toplamak için kullanılmıştır.
             - 
    asm ("cpuid"
                : "=a" (_eax),
                  "=b" (_ebx),
                  "=c" (_ecx),
                  "=d" (_edx)
                : "a" (op));
- 
              Aşağıda bunun için üretilmiş Sembolik Makina Dili kodunu görebilirsiniz
              (_eax ,_ebx vb ... değişkenlerin yığıtta bulunduğu varsayılmıştır):
             - 
        movl -20(%ebp),%eax     /* 'op' yi %eax te tut -- girdi */
#APP
        cpuid
#NO_APP
        movl %eax,-4(%ebp)      /* %eax i _eax te tutar -- çıktı */
        movl %ebx,-8(%ebp)      /* diğer yazmaçları kendi çıktı
        movl %ecx,-12(%ebp)        değişkenlerinde tutar */
        movl %edx,-16(%ebp)
- 
              Aşağıdaki yolda strcpy fonksiyonu "S"
              ve "D" belirteçleri kullanılarak uygulanabilir:
             - 
    asm ("cld\n
              rep\n
              movsb"
              : /* girdi yok */
              :"S"(src), "D"(dst), "c"(count));
- 
              Kaynak gösterge src %esi'ye
              "S" belirteci ve hedef gösterge
              dst'ye "D" belirteci kullanılarak
              yerleştirilmiştir. Sayaç değeri rep önekinin
              gerektirdiği gibi %ecx'e yerleştirilmiştir.
             - 
              Ve burada da 32-bit kodları birleştirip 64-bit kod elde etmek için,
              %eax ve %edx olmak üzere iki
              yazmaç kullanan bir belirteç göreceksiniz:
             - 
#define rdtscll(val) \
     __asm__ __volatile__ ("rdtsc" : "=A" (val))
- 
              Üretilen Sembolik Makina Dili kodu şuna benzer
              (val 64 bit bellek alanına sahipse):
             - 
#APP
        rdtsc
#NO_APP
        movl %eax,-8(%ebp)      /* A belirtecinin sonucu olarak
        movl %edx,-4(%ebp)         %eax ve %edx çıktı gibi çalışır */
- %edx:%eax'in içindeki değerler 64 bit çıktı gibi çalışır.
             
- Karşılaştırma belirteçlerinin kullanımı
- 
              Burada da dört parametreli sistem çağrıları için kodları göreceğiz:
             - 
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
        : "=a" (__res) \
        : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
          "d" ((long)(arg3)),"S" ((long)(arg4))); \
__syscall_return(type,__res); \
}
- 
              Üstteki örnekte sistem çağrısına dört argüman %ebx, %ecx, %edx
              ve %esi'ye b, c, d ve S
              belirteçleri kullanılarak bırakılmıştır. "=a" belirteci çıktıda
              kullanılmıştır. Bundan dolayı sistem çağrısının dönen değeri %eax,
              __res değişkenine aktarılır. Karşılaştırma belirteçlerinden
              "0"'ı girdi bölümünün ilk teriminin belirteci olarak kullanarak,
              sistem çağrısı numarası __NR_##name %eax'e atanır ve sistem
              çağrısın girdisi olarak işlem görür. Böylece %eax burada hem
              girdi hem de çıktı yazmacı olarak çalışır. Bunun için iki farklı yazmaç kullanılmadı.
              Ama şu unutulmamalıdır ki girdi (sistem çağrı numarası) çıkış üretilmeden önce
              kullanılmalıdır.
             
- Bellek terimi belirtecinin kullanımı
- 
              Aşağıdaki küçük azaltma işlemini inceleyin:
             - 
    __asm__ __volatile__(
                "lock; decl %0"
                :"=m" (counter)
                :"m" (counter));
- 
              Bunun için üretilen Sembolik Makina Dili kodu şöyle olur:
             - 
    #APP
        lock
        decl -24(%ebp) /* sayaç bu bellek bölümünde değiştirilir. */
#NO_APP.
- 
              Burada sayaç için yazmaç belirteci kullanmadan önce bir düşünmelisiniz.
              Eğer kullanırsanız, önce sayacın içeriğini bir yazmaca atamalısınız.
              Azaltma işlemini yaptıktan sonra sonucu belleğine atamalısınız. Ama o
              zaman da lock kullanma ve kodu küçük tutma
              çabamızı boşa çıkarmış oluruz. Bu bellek belirtecinin gereğini kesin
              olarak göstermektedir.
             
- Geri Dönen yazmaçların Kullanımı
- 
              Temel Bellek Kopyasının işlemesini inceleyin.
             - 
        asm ("movl $count, %%ecx;
              up: lodsl;
              stosl;
              loop up;"
                :                       /* çıktı yok */
                :"S"(src), "D"(dst)     /* girdi */
                :"%ecx", "%eax" );      /* geri dönen yazmaçlar */
- 
              lodsl %eax'i değiştirirken, lodsl ve
              stosl komutları onu dolaylı olarak kullanır.
              %ecx yazmacı doğrudan count'u çağırır.
              Biz %eax ve %ecx'i geri dönen
              yazmaçlar listesinde belirtmediğimiz sürece GCC bunun farkında olmayacaktır.
              Bunu yapmadığımız sürecce GCC %eax ve %ecx'in
              serbest olduğunu varsayar ve onları başka bilgiler tutmak için kullanabilir.
              Şunu bilmelisiniz ki %esi ve %edi "asm"
              tarafından kullanılıyor ve geri dönen yazmaçlar arasında belirtilmemişlerdir.
              Çünkü onlar zaten girdi terimlerinin listesinde bulunmaktadırlar. Ve son olarak,
              eğer dolaylı veya doğrudan kullanılmış bir yazmaç girdi veya çıktı listesinde
              bulunmuyorsa, onu geri dönen yazmaçlar listesine yazmalısınız.