Arduino
OKUDUĞUNUZ KONU
ASSEMBLY Dili ile Arduino Kodlama
0

ASSEMBLY Dili ile Arduino Kodlama

Yazar : Turgut Güneysu5 Kasım 2018

 

Merhaba,

Bugün ARDUINO UNO’ya  işlemcilerin ana dili olan ASSEMBLY dilinde nasıl kodlama yaparız ona bakacağız. ARDUINO proje geliştirirken kullanılan IDE ve arkasındaki GCC derleyicisi C-kod arasına yazılan ATmega328 Assembly komutlarını (inline Assembly) gayet rahat bir şekilde entegre edebildiğinden bu iş gayet da kolay bir şekilde başarılabilir.

Peki bunun faydası nedir diye düşünüyorsanız, şu listeyi inceleyin:

  • program çalışma hızı – ASM kodları Arduino kodlarına nazaran defalarca daha çabuk çalışır.
    Örneğin: 10K pin 8-13 yak/söndür döngüsü – Arduino süresi: 459ms            ASM süresi: 7ms
  • kod ve bellek boyutları – Fonksiyonları tamamen arzunuza göre kodladığınızdan ve donanıma çok yakın çalıştığınızdan kodlarınız gayet az bellek kullanır.
    Örneğin: Arduino BLINK – avrdude: 948 bytes of flash written
                  Benim ASM BLINK – avrdude: 482 bytes of flash written
  • gerçek zamanlı donanım kontrolü – yukarıdaki “hız” ile ilgili olarak işlemler çok daha çabuk ve gerçek zamana yakın çalıştığından donanım kontrolleriniz kritik uygulamalarda daha iyi sonuç verir.
  • kod optimizasyonu – Donanıma direkt müdahaleden dolayı yazdığınız kodlar Arduino fonksiyonlarına nazaren çok daha optimize çalışır. Ayrıca, Arduino’nun yarattığı kodları inceleyip, kodun en fazla zaman aldığı yerleri özel olarak yeniden yazıp hızlandırabilirsiniz.

Assembly dilinin detaylarına fazla girmeyeceğiz. Bu çok derin ve geniş bir konu, ilgilenenler Internet’ten yeterli bilgi edinebilirler. Odaklanmak istediğimiz konu, bu dili ARDUINO IDE ortamında nasıl kullanacağımız ve buna yardımcı birkaç yan bilgiler.

Ana örneğimiz olarak herkesin bildiği temel Arduino BLINK projesine bakacağız.

Temel Kavramlar

İlk önce ATmega328P işlemcisinin saymaçlarını, girdi/çıktı komutlarını ve bellek düzen detaylarını incelememiz lazım.

1. PORT Saymaçları

ATmega328P işlemcisindeki 8 bit PORT saymaçları Arduino port girdi çıktılarını en süratli şekilde değiştirmenizi sağlar. Arduino’da üç grup PORT’lar bulunur:

  • B (dijital pinler 8 – 13)
  • C (analog pinler A0- A5)
  • D (dijital pinler 0 – 7)

Bu portlar üçer tane PORT saymacı tarafından kontrol edilir:

  • DDRB/C/D – pinlerin INPUT (girdi) ve OUTPUT (çıktı) olarak ayarlanmasını
  • PORT/B/C/D – pinlerin HIGH (yüksek) ve LOW (alçak) değerlerine ayarlanmasını
  • PIN/B/C/D – pinlerin pinMode() kullanarak ayarlanan girdi çıktı mod’larının okunmasını

sağlar. DDR ve PORT saymaçları hem yazılır hem okunur. PIN saymacı yalnız okunur. Bu saymaçların her bir bit’i Arduino’nun bir pinini kontrol eder.

             --- Saymaç bitleri ---
             7  6  5  4  3  2  1  0
DDRB pin:         13 12 11 10  9  8
DDRB ayarı:        1  1  0  1  0  0    <- Örneğin: Pin 10,12,13 OUTPUT ve 8, 9, 11 INPUT ayarlanmış

PORTD pin:   7  6  5  4  3  2  1  0
PORTD ayarı: 1  1  1  0  0  1  tx rx   <- Örneğin: Pin 3, 4 LOW ve 2, 5, 6, 7 HIGH ayarlanmış

Daha fazla bilgi için Arduino referans sayfasına bakın: PORT işlemleri. PORT saymaçlarını ilk anlattığım başka bir yazı için de şu bağlantıya bakabilirsiniz: Arduino-Tinkercad-Proje-3.

PIN ve PORT kavramlarıyla çalışırken dikkat etmeniz gereken en önemli nokta dijital pin sıfır (D0). Bunu hiç bir zaman OUTPUT (çıktı) olarak ayarlamayın. Bu Arduino’nun RX (receive – veri alış) pini olduğu için yanlış ayarladığınızda Arduino’nun SERİ bağlantısı etkilenebilir. Ayrıca 8 bit saymaçların atanacağı değerlerin 0 – 255 arası olduğunu da aklınızda tutun.

2. Zaman Geciktirme

AVR komut kümesinde işlemciyi bir çevrim (62,5 nanosaniye) için durduran NOP (No Operation) dışında başka yerleşik zaman geciktirme talimatı yoktur. Bu da mümkün olan en küçük zaman gecikmesidir. Mili-saniye veya daha uzun bir süre gecikme yapmak için döngüler kullanılmalıdır.

Döngülerin yürütüm süresi döngü içinde kullanılan komutların çevrim toplamına göre hesaplanır. ATmega328P işlemcisinin detaylarına şu bağlantıdan ulaşabilirsiniz. “36. Instruction Set Summary” (Komut Küme Özeti) sayfalarında komut çevrimleri en sağ “#Clocks” sütunu altında belirlenmiştir.

Aşağıda, assembly dilinde, tahminen bir saniye sürecek bir geciktirme kod örneği sunuyorum:

"BirSaniye:                  \n\t"    //dış döngü
   "LDI   r16, 80            \n\t"
"0: CPI   r16, 0             \n\t"
   "BREQ  1f                 \n\t"
//-----------------------------------------------------------------
   "LDI   r17, 200           \n\t"    //iç döngü
"2: CPI   r17, 0             \n\t"
   "BREQ  3f                 \n\t"
//-----------------------------------------------------------------
   "LDI   r18, 200           \n\t"    //en iç döngü
"4: CPI   r18, 0             \n\t"
   "BREQ  5f                 \n\t"
   "SUBI  r18, 1             \n\t"
   "RJMP  4b                 \n\t"
"5:                          \n\t"
//-----------------------------------------------------------------
   "SUBI  r17, 1             \n\t"
   "RJMP  2b                 \n\t"
"3:                          \n\t"
//-----------------------------------------------------------------
   "SUBI  r16, 1             \n\t"
   "RJMP  0b                 \n\t"
"1: RET                      \n\t" //1 saniye geciktirme

İç içe üç döngü olarak düzenlenmiş olan kodlama 200 x 200 x 80 kere olarak çalıştığında döngü toplamı 3.200.000 oluyor. Her döngü de ortalama 5 çevrimlik komutlardan oluştuğu için 16MHz bir Arduino’da bu bize 16.000.000 çevrim vererek aşağı yukarı 1 saniyelik bir geciktirme sağlıyor.

Arduino 8 bit bir işlemci olduğundan, herhangi bir saymaca yüklenecek en büyük sayı 255 dir. Daha yüksek sayılarla çalışmak gerektiğinde birden fazla saymacı kullanarak ve peş peşe döngülerle bu amaca ulaşabiliriz.

Şimdi aranızda herhalde değişik değerlerde geciktirme hesapları yapmanın gayet saçma olduğunu ve bundan daha önemli işlerle uğraşması gerektiğini düşünenler vardır. Tabi ki her zaman olduğu gibi, bu konuda da Internet gene yardımımıza geliyor. AVR Delay Loop Calculator (AVR Gecikme Döngüsü Hesap Makinesi) sitesi bu işi otomatize ederek bu problemimizi çözüyor. Bunu nasıl kullanacağımızı bir az sonra göreceğiz.

3. SRAM Veri Belleği

Yukarıdaki resim SRAM veri bellek düzenini gösteriyor. İlk 32 bayt işlemci saymaçlarına, sonraki 64 bayt G/Ç saymaçlarına ayrılmış. Bunun arkasından 160 baytlık genişletilmiş G/Ç saymaç alanı ve 2048 baytlık SRAM geliyor.

ATmega işlemcisinin iki tür G/Ç komutları var:

  1. Tek çevrimle çalışan IN/OUT ve
  2. birden fazla çevrimle çalışan LOAD/STORE komutları.

IN/OUT komutları, komut biçimlerinden dolayı, yalnız 00-3F arasındaki 64 belleğe ulaşabiliyor. Fakat tek çevrimden dolayı çok süratli çalısıyor.

LOAD/STORE komutları tüm 00-08FF arasındaki 2303 belleğe ulaşıyor. Fakat birden fazla çevrimden dolayı daha yavaş çalışıyor.

Komutlar belleklerle çalışırken beş değişik adresleme modu kullanıyorlar:

  1. Doğrudan Adresleme – tüm veri alanına ulaşır.
  2. Yer değiştirme ile dolaylı adresleme – temel adres ve Y veya Z adres saymaç değerlerinden oluşan 64 adres konumuna ulaşır.
  3. Dolaylı Adresleme – R26-R31 saymaç değerlerinden oluşan X, Y, ve Z dolaylı adres saymaçlarını kullanır.
    X: R27:r26   Y: R29:r28   ve   Z: R31:r30
  4. Ön azaltma ile dolaylı – X, Y, ve Z adres saymaç değerleri komuttan önce azaltılır.
  5. Artış sonrası dolaylı – X, Y, ve Z adres saymaç değerleri komuttan sonra artırılır.

Cihazdaki tüm dahili SRAM veri belleğine bu adresleme modları aracılığıyla erişilebilir.

4. Memory-Mapped I/O (Bellek Eşleşmeli G/Ç )

Bellek eşlemeli G/Ç, donanımın sistem belleğine eşlenen yazmaçlara veya bellek bloklarına okuma ve yazma yoluyla, donanım çevre birimlerini denetlemek için kullanılır. MMIO düşük düzeyli çevre birimi kontrolünü mümkün kılar. Bu yazıda ATmega328P işlemcisine odaklandığımız için sizi şu bağlantıda 18.4.2. kısmındaki bilgilere yönlendirmek isterim: atmel-42735-8-bit-avr-microcontroller-atmega328-328p_datasheet.pdf .

Yukarıdaki bellek eşleşmeli G/Ç tanımlamasının ana fikri, Arduino pinlerine değişik bellek adreslerini kullanarak ulaşabileceğimizdir. Aşağıdaki tablo bu adresleri tanımlar:

 PINB  IOreg = 0x03     offset = 0x23
 DDRB  IOreg = 0x04     offset = 0x24  
 PORTB IOreg = 0x05     offset = 0x25
 PINC  IOreg = 0x06     offset = 0x26
 DDRC  IOreg = 0x07     offset = 0x27
 PORTC IOreg = 0x08     offset = 0x28
 PIND  IOreg = 0x09     offset = 0x29
 DDRD  IOreg = 0x0A     offset = 0x2A
 PORTD IOreg = 0x0B     offset = 0x2B

Burada dikkatinize çekilecek şey tüm saymaçların iki değişik adres ile çalışmasıdır: IOreg adresi ve Offset adresi. İkisinin arasındaki farkın da 0x20 olmasıdır. IN/OUT komutlarını kullanmak isterseniz IOreg adreslerini, LOAD/STORE komutlarını kullanmak isterseniz offset adreslerini kullanmanız gerekir.

5. AVR Gecikme Döngüsü Hesap Makinesi

AVR Delay Loop Calculator sitesi ASM dilinde kullanmak istediğimiz gecikme döngü kodlarını bize otomatikman veren bir site. Bunu nasıl kullanacağımızı inceleyelim:

  • Bu siteyi çevrimiçi kullanmak istiyorsanız, yukarıdaki bağlantıdan ulaşıp hemen kullanmaya başlayabilirsiniz.
  • Eğer çevrimdışı kullanmak istiyorsanız, sayfayı tarayıcınıza yükleyin. Yüklendikten sonra fare sağ tuşuna basıp “Farklı Kaydet” seçin ve “Web Sayfası, Tamamı” olarak bilgisayarınıza kaydedin. Bundan sonra Internet’e bağlanmadan kullanabilirsiniz.

Bu programın ilk kırmızı karesine işlemcinizin frekansını girin. Arduino UNO: 16MHz.

İkinci kırmızı karesine “ne kadar gecikme” istediğinizi girin. Burada 1 saniye gösteriliyor. Sonra da sağ taraftaki zaman birimlerinden birini seçin.

“GO” butonuna basınca alt tarafta kodunuz oluşacaktır. GO buton altında üstünde iki tane seçenek düğmesi göreceksiniz: biri assembler kod için, diğeri ise avr-gcc tipinde kod için. Biz buradaki kodu Arduino’nun avr-gcc derleyicisi ile kullanacağımız için, avr-gcc olanı seçin.

Kodun sarı kısmını kes / yapıştır ile programımıza aktarabiliriz.

Bu uygulamanın kodunu anlamak isteyenler şu linkten detaylarını inceleyebilirler: improved-delay-loop-calculator .

Arduino ve Assembly Kod Entegresi

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 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 kodlamayı tamamlar.

Aşağıda bu entegreyi gösteren ufak bir örnek sunuyorum:

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 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. benimNum değ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 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:

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 —

ARDUINO Derleyici DİZİN ve DOSYALARI

Yazdığınız Arduino kodları   Verify/Compile (Denetle/Derle) veya Upload (Yükle) seçtiğinizde derleyici tarafından işlenip Arduino’ya yüklenecek HEX formatında bir dosya haline getirilir. Bunlar her butona bastığınızda işlenip bilgisayarınızdaki bir dizine yazılır. Bu yöntemi kodlama ekranı altındaki alanda izleyebilirsiniz:

Eğer aynı tip bir listeleme görmüyorsanız, aşağıdaki resimde gösterilen Arduino seçeneklerinden “Show verbose output during” ve “Editor Font Size” ayarlarını aynen yapın. Birincisi detaylı derleme mesajlarını gösterecektir. İkincisi ise kodlama altındaki yazıların boyutu ile ilgili. Eğer zor okunuyorsa, daha yüksek değerde bir font size seçin.

Simdi bu siyah renkteki alana yazılan satırların detayına bakalım:

“Sketch uses 478 bytes…” diye başlayan satırın hemen üstündeki satır bizim odaklanacağımız satır, bunu bulun. Ekran resmi kırpılmış çıktığından bu uzun satırı aşağıda tek başına yazıyorum:

"C:\Users\Turgut\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2/bin/avr-objcopy" -O ihex -R .eeprom "C:\Users\Turgut\AppData\Local\Temp\arduino_build_944010/ASM_BLINK.ino.elf" "C:\Users\Turgut\AppData\Local\Temp\arduino_build_944010/ASM_BLINK.ino.hex"

Sizinki tabi ki kullanıcı ad değişikliğinden biraz başka olacaktır. Mühim olan satırın ortasındaki kalın font’da belirlediğim çok uzun dosya adı:

"C:\Users\Turgut\AppData\Local\Temp\arduino_build_944010/ASM_BLINK.ino.elf"

Bu bizim BLINK programımızın derleyici tarafından yaratılan dosyalarından biri.

Bunun başlangıcındaki “C:\Users\Turgut\AppData\Local\Temp\arduino_build_944010/” dizini derleyicinin yazdığınız programın tüm dosyalarını yazdığı yerdir. Bir komut penceresi açıp, konumunuzu bu dizin yerine değiştirin:

CD  “C:\Users\Turgut\AppData\Local\Temp\arduino_build_944010/”

Arkasından DİR komutu ile buradaki dosyaları listeleyin. Yukarıdaki resimde gördüğünüz gibi bir listeye ulaşmanız gerekiyor.

Buradaki dosyalar, sizin    butonlarına bastıktan sonra yaratılan dosyalardır. Bunların arasında bizim enterese olduğumuz .ELF uzantılı dosya.

Bu dosyayı AVR-GCC dereyicisi kumandaları ile ASSEMBLER kod listesi halinde görüntüleyebiliriz:

avr-objdump -S  ASM_BLINK.ino.elf  >  ASM_BLINK_Listem.txt

İnceleyelim:

avr-objdump -S    yaratılan HEX kodun hem ASSEMBLY hem de C-KOD derleyici listesini yaratan komut

ASM_BLINK.ino.elf     derleyicinin girdi olarak kullanılan dosya adı

>    önceki dosyanın çıktısını sonraki adlı dosyaya yaz

ASM_BLINK_Listem.txt    derleyicinin yaratacağı ve bizim adlandırdığımız çıktı dosyası.

Bu dosyayı herhangi bir düzenleyici ile inceleyebilirsiniz.

NOT:

avr-objdump programı genelde Arduino programının kurulduğu dizin altında bir yerde bulunur. Benim bilgisayarımda bu:

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin

adlı dizinde. Eğer bu dizin adı bilgisayarınızın varsayılan PATH listesinde değilse eklemeniz gerekir. Yoksa programın tam yol adını kullanmanız gerekir.

Aşağıda avr-objdump programının kullanım seçenek detayları:

Usage: avr-objdump
Display information from object .
At least one of the following switches must be given:
-a, --archive-headers Display archive header information
-f, --file-headers Display the contents of the overall file header
-p, --private-headers Display object format specific file header contents
-h, --[section-]headers Display the contents of the section headers
-x, --all-headers Display the contents of all headers
-d, --disassemble Display assembler contents of executable sections
-D, --disassemble-all Display assembler contents of all sections
-S, --source Intermix source code with disassembly
-s, --full-contents Display the full contents of all sections requested
-g, --debugging Display debug information in object file
-e, --debugging-tags Display debug information using ctags style
-G, --stabs Display (in raw form) any STABS info in the file
-W, --dwarf Display DWARF info in the file
-t, --syms Display the contents of the symbol table(s)
-T, --dynamic-syms Display the contents of the dynamic symbol table
-r, --reloc Display the relocation entries in the file
-R, --dynamic-reloc Display the dynamic relocation entries in the file
@ Read options from
-v, --version Display this program's version number
-i, --info List object formats and architectures supported
-H, --help Display this information

Gelişmiş Projeler

  • Arduino ve Assembly Kod Entegresi kısmında verdiğim kısa programı kullanarak, değişkenlere ASM dilinden ulaşmayı deneyebilirsiniz.
  • BLINK projesinin donanım kısmına değişik LED’ler ekleyip, bunları aynı kod üzerinden bit maskelerini değiştirerek çalıştırabilirsiniz.
  • BLINK projesinin geciktirme değerlerini değiştirebilirsiniz.
  • PWM değerleri 0-255 arası değiştiğinden ASM saymaç uygulamalarına gayet uygundurlar. Bir dijital porta motor bağlayıp, bunu saymaç değer kontrolü ile çalıştırabilirsiniz.
  • Kod hız araştırması: buradan indireceğiniz program değişik tekniklerle port manipulasyon örnekleri sunuyor. Bununla oynayıp kod çevrimleri hakkında daha derin algılama yapabilirsiniz. Kullanmadan önce, indirdiğiniz kodun eklentisini .INO yapın.

Evet, işte yazımızın sonuna geldik. Umarım buradaki bilgileri uygulayarak projelerinizi zenginleştirir, ASM yardımıyla gereken yerlerde daha hızlı çalışan bir uygulamayı başarırsınız.

İyi çalışmalar.

SİZCE NASIL OLMUŞ?
Beğendim
100%
İlginç
0%
Eh İşte
0%
Anlamadım
0%
Kötü
0%
Berbat
0%
YAZAR HAKKINDA
Turgut Güneysu
Turgut Güneysu
Anadolu'nun tam ortasında ufak bir köyden memleketimizin çocuklarına STEM programlarına uygun bilgisayar, robotik, yazılım, donanım, mikro işlemciler hakkında yardımcı olmaya çalışıp, emekli hayatımın zevkini çıkarıyorum. Gençlerimizin kabiliyetlerinin sonsuz olduğuna ve onları doğru yönlendirirsek değerli katkılarla ortamımızı dünya çapına ulaştıracaklarına inanıyorum.
YORUMLAR

YORUM YAP