• Hesap Oluştur
  • Oturum Aç

Arduino ve Assembly Kod Entegresi

admin    0

    • avatar

    admin  23-03-2019, 12:40

    Kredi:
    #1
    Arduino ve Assembly Kod Entegresi nasıl olur?
    Arduino IDE’sinde çalışırken genelde C’ye benzeyen bir lisanda kodlama yapılır. Buna ilaveten özel bir fonksiyon kullanarak Assembly lisanı da kullanılabilir. Arka planda da Arduino kodlarını işleyen GCC derleyicisi C-Kod ve assembly lisanda yazılmış kodların tümünü entegre edip Arduino’ya yüklediğimiz en son da kodlamayı tamamlar.
    Aşağıda bu entegreyi gösteren ufak bir de örnek sunuyorum:
    Alıntı: volatile byte benimNum = 10;
    void setup() {
    Serial.begin(9600);
    Serial.print("ASMden önce...");
    Serial.println(benimNum);
    asm (
      "lds r16, (benimNum) \n" // benimNum değişkenini saymaç r16'ya yükle
      "inc r16 \n"             // r16 saymacını 1 artır
      "sts (benimNum), r16 \n" // r16 saymaç değerini benimNum değişkenine yükle
    );
    Serial.print("ASMden sonra...");
    Serial.println(benimNum);
    }
    void loop() { }
    Örnekte benimNum değişkeni tanımlanıp 10 değeri de atanıyor. Seri port hız ayarından sonra “ASMden önce…10” olarak bu değer Seri monitöre yazılıyor. Arkasından asm( ) komutuyla assembly diline geçiliyor. benimNumdeğişken değeri r16 saymacına yükleniyor ve saymaç bir artırılıyor. Sonra yeni saymaç değeri (11) tekrar benimNum değişkenine yükleniyor. Ve Seri monitöre bu yeni değer “ASMden sonra…11” olarak yazılıyor.
    Bu basit örnekte önemli olan kodun ne yaptığı değil, kullanılan sözdizimidir:
    • Gördüğünüz gibi, standart Arduino değişken tanımı ve üç tane ‘Serial’ komutundan sonra gelen asm( ); komutu kullanılan dili assembly’ye geçiriyor. Yani asm(); Arduino kodunun bir fonksiyonu gibi davranıyor.

    • Her asm kod satırı “…” arasına yazılıyor.

    • Her satır tek bir ASM komutundan oluşuyor.

    • BLINK örneğindeki gibi “bekle:” tipinde etiketler hem altyordam hem de döngüler için kullanabiliyor.

    • Satır sonları kod listelemesini daha kolay okuyabilmek için \n kontrol karakteri ile sonlanıyor.

    • “…” dan sonra istenirse // kullanarak, Arduino kodundan olduğu gibi, açıklama yazılabiliyor.

    • asm( ); den sonra tekrar Arduino koduna geçilebiliyor.

    • Arduino kod … asm kod … Arduino kod sözdizimi istenildiği kadar tekrarlanabiliyor.
    Burada gördüğünüz asm sözdizimi kuralları sizi assembly dilini denemeye başlatacak temel kurallardır. Fakat bunların ötesinde ve burada anlatmamıza imkan olmayan değişik bir sürü kural daha vardır. Unutmayın ki, Assembly dili her işlemci için değişik olup, işlemci yapısına göre de değişik komutlar içerir. Bundan dolayı bu dilde çalışmak özel bir yaklaşım gerektirir.
    Daha geniş bir çalışma arzu edenler, “Official AVR-GCC Inline Assembler Cookbook” adlı sayfaları inceleyebilirler. Veya “Inline Assembler” terimini arayarak Internet’ten daha detaylı bilgi edinebilirler.
    Assembly ile de BLINK Projesi
    Buraya kadar takip edebildiyseniz, simdi BLINK projesini assembly dilinde yazmaya başlayalım:
    • Yakıp söndüreceğimiz led Arduino ana kartı üzerindeki LED13 dür.

    • Led yanıp sönme süresini 200ms olarak ayarlayacağız.

    • LED13’e ulaşabilmek için IOreg adres modunu kulanacağız.

    • LED13’ü yakıp söndürmek için EOR (dışlamalı veya operatörü) işleminden yararlanacağız.
    Aşağıdaki kodumuzu satır satır inceleyelim:
    Alıntı: 001 /*  ASM diliyle BLINK
    002      Bu program ATMEGA'nın PIN, DDR ve PORT yazmaçlarını kullanarak
    003      PIN ayarları yapmayı gösteriyor.
    004      Kod IOreg adresi tekniğini kullanıyor.
    005
    006      PINB  IOreg = 0x03     offset = 0x23
    007      DDRB  IOreg = 0x04     offset = 0x24  
    008      PORTB IOreg = 0x05     offset = 0x25
    009      PINC  IOreg = 0x06     offset = 0x26
    010      DDRC  IOreg = 0x07     offset = 0x27
    011      PORTC IOreg = 0x08     offset = 0x28
    012      PIND  IOreg = 0x09     offset = 0x29
    013      DDRD  IOreg = 0x0A     offset = 0x2A
    014      PORTD IOreg = 0x0B     offset = 0x2B
    015
    016      SAYMAÇLAR:  X: r27:r26          Y: r29:r28          ve Z: r31:r30
    017 */
    018
    019 void setup() {
    020   DDRB = DDRB | B00100000;      // d13 ÇIKTI olsun
    021
    022   asm  (
    023     "jmp basla \n"
    024     "bekle: \n"                 // 200ms geciktirme
    025     "    ldi  r18, 17"    "\n"
    026     "    ldi  r19, 60"  "\n"
    027     "    ldi  r20, 204" "\n"
    028     "1:  dec  r20"  "\n"
    029     "    brne 1b"   "\n"
    030     "    dec  r19"  "\n"
    031     "    brne 1b"   "\n"
    032     "    dec  r18"  "\n"
    033     "    brne 1b"   "\n"
    034     "    ret \n"
    035    
    036     "basla: \n"
    037     "ldi r21, 0b00100000 \n"   // PORTB ayarı saymaç r21'e yükle (D13 on)
    038   );
    039 }
    040
    041 void loop() {
    042   asm  (
    043     "in r22, 0x3 \n"           // PINB (IOreg = 0x03) değerleri r22 ye yükle
    044     "eor r22, r21 \n"          // LED13'ü pinini XOR'la
    045     "out 0x5, r22 \n"          // PORTB saymacını güncelle (IOreg = 0x05)
    046     "call bekle \n"
    047   );
    048 }
    001-018: Program açıklamaları
    019-021: SETUP kısmının başlangıcı. DDRB saymacı kullanarak D13 pinini OUTPUT (Çıktı) olarak ayarlıyoruz. DDRB saymacı dijital 8-13 pinlerini kontrol eder. Bu saymaç değerine ikili sabit B00100000 ile mantıksal OR (ve) işlemini uygulayınca D13 pinine rastgelen DDRB bit’ini 1 yapmış oluyoruz. Yani D13’ü çıkış olarak ayarlıyoruz.
    022-040: Assembly dilinde kodumuzun ilk kısmı.
    023: Satır 024-034 arasındaki bekle etiketli 200ms geciktirme kodunu işlemeden üzerinden basla etiketine atlıyoruz.
    024-034: bekle adını verdiğimiz 200ms geciktirme kodu. Bunu AVR Gecikme Döngüsü Hesap Makinesi sayfasından aldık. Bu kodun bir alt yordam olarak çalışması gerektiğinden, siteden aldığımız kodun önüne bir etiket (“bekle: \n”) sonuna ise bir (” ret \n”) komutu ekledik. RET komutu kodun bu satırına gelindiğinde RETURN (geri dön) işlemiyle geciktirme kodunu çağıran yere geri döner.
    035-036: basla etiketi. Önündekii boş satır sadece kolay okunsun diye.
    037:  İkili sabit 0b00100000 değerini r21 saymacına bit maskesi olarak yüklüyoruz. PORTB saymacı dijital 8-13 pinlerini kontrol ettiğinden bu sabit değerdeki 1 bit’i D13 pinini belirtiyor. r21 saymacı tamamen bizim isteğimizle seçilmiş bir saymaç.
    038: ASM kodun sonunu belirten “)” parantez.
    039: SETUP sonu.
    041-048: LOOP döngüsü.
    042: LOOP içindeki assembly kodumuzun başlangıcı.
    043: PINB (IOreg = 0x03) saymacındaki anlık pin durum değerlerini r22 saymacına okuyoruz.
    044: EOR işlemi: r21’de sabit bit maske değeri 0b00100000 var. r22’de 8-13 dijital pinlerin anlık durumu var. EOR işlemi bittiğinde r22 deki değer r21’in içindeki 1 bit’in olduğu yerde aksine dönüyor. r21 değeri aynı kalıyor. Bunu tekrarladığımızda r22 değeri gene r21’in içindeki 1 bit’in olduğu yerde aksine dönüyor. Böylece EOR kullanarak d13 pin ayarını 0 ve 1 arasında değiştiriyoruz.
    045: OUT komutu r22 saymacındaki değişmiş değeri PORTB saymacına (IOreg = 0x05) yazıyor. Yani D13 led’in yanıp sönmesi donanıma yansıtılıyor.
    046: 200ms gecikme yapan bekle alt yordam çağrılıyor. 024-034’de anlatıldığı gibi, bekle bitince bu noktaya geri döner.
    047: ASM kodun sonu.
    048: LOOP döngüsü sonu.
    — KOD SONU —
    Gelecek Yapay Zeka İle Gelecek
    Beğeni

Bu konuyu görüntüleyen kullanıcı(lar): 1 Ziyaretçi

Foruma Git: