Kütüphane Oluşturmak

Başlatan Tagli, 09 Mart 2011, 21:00:14

Tagli

Daha yeni yeni yeniden konumlandırılabilir (reallocatable) kod yazımını öğreniyorum/deniyorum. Çok sevdiğimi söyleyebilirim. Bu işi öğrenmek için bir GLCD kütüphanesi yazma işine giriştim, iyi kötü de bir şeyler çıktı ortaya.

Ben eğitim amaçlı bu projemde, glcd.asm diye bir dosya oluşturup ilgili kodları burada yazdım. Dışarıdan kullanılacak etiketleri global diyerek işaretledim. glcd_test.asm isimli deneme dosyasında ise bunları extern ile içe aktardım. Font dosyasını da ayırıp aynı yöntemle içindeki etiketi glcd.asm'ye dahil etmem gerekti. Yazmayı düşündüğüm makroları ise hangi dosyaya nasıl ekleyeceğim konusunda bir fikrim yok. Ayrıca tüketici konumundaki glcd_test.asm'nin başında bir dolu extern başlıklı etiket olması mantıklı gelmedi bana.

Sorularım şunlar: Assembly dilinde kütüphanelerin yapısı ve genel biçimleri nasıl olur? Benim yaptığım şekilde kodlar birbirine global ve extern işaretlenmiş etiketler ile mi bağlanır (ki bu bana mantıklı gelmiyor)? Makrolar hangi dosyaya eklenir ve dışarıdan erişime nasıl açılır? Onları da glcd.asm'ye yazmam gerekiyor? Librarian kullanarak .lib uzantılı dosyaları nasıl elde ederim ve bunları kullanacak kişi bunları nasıl projesine dahil eder? Yukarıda bahsetmiş olduğum extern - global ikililerini kullanmadan tüketici koda kütüphane eklenmesi, mesela include benzeri bir şekilde, nasıl yapılır? Assembly'de yazılıp C18'de kullanılabilen kütüphaneleri nasıl oluşturabilirim?
Gökçe Tağlıoğlu

Tagli

#1
Yukarıdaki durum için şöyle bir yöntem izleyeyim dedim: glcd_test.asm içindeki externli ifadeleri ve yazacağım makroları (denemek için bir tane yazdım) yeni oluşturduğum glcd.inc dosyasının içine koydum. Bunu da projeye ekleyerek glcd_test.asm içinde "include glcd.inc" şeklinde ekledim. Tam istediğim gibi derlendi sandım, ama derlenmemiş.

Sorun şu: hex dosyasının içinde glcd_test.asm içindeki kodlar yok. Haliyle hiçbir şey çalışmıyor. hex içinde glcd.asm ve Font8x8.asm içindeki kodlar var. Hatta fontlar hex'in hemen başına oturmuş  :o. Gerçi daha önce de öyleydi ama hemen başta goto vardı ve programı ilgili yere götürüyordu. glcd.inc içindeki kodu (ki sadece externli etiket ifadelerinden ve 1 adet makrodan oluşuyor) kopyala - yapıştır ile glcd_test.asm içine atıp include ifadesini kaldırdığımda doğru şekilde derleniyor.

Bu include işinde nereyi yanlış yapıyorum?

Düzeltme: Hatamı buldum. glcd.inc'i ilk oluşturduğum sırada yanlışlıkla başka bir proje klasöründe oluşturup oradan eklemiştim. Haliyle derlenmemişti. Hatayı farkedince dosyayı projeden çıkarıp doğru yere taşıyıp tekrardan projeye eklemiştim. Ancak gerçekte olmayan dosya garip bir şekilde MPLAB'da açık kalmış ve eski yerinde tekrardan oluşmuş.

Sorunun asıl kaynağı şu: glcd.inc sonuna END yazmıştım, bu yüzden glcd_test.asm, bu dosyayı include ettikten sonra sonlanıyormuş. Denemelerim sırasında bu ihtimali düşündüğümden END'i silip denemiştim. Ama silip kaydettiğim dosya diğer klasörde yeniden oluşmuş dosya imiş. Yani ben değişik şeyler denerken gerçekte kullanılan glcd.inc hiç değişmiyormuş.  :P
Gökçe Tağlıoğlu

Tagli

Bu başlıkta kendim çalıp kendim oynuyorum gibi gözüküyor ama ben yine de derdimi yazayım...

Yukarıda bahsettiğim sorunlar büyük ölçüde çözüldü. Şu anda kullandığım yapıyı ve görevlerini özetleyeyim:

glcd.asm -> #define kullanılarak yapılmış bacak tanımlamaları dahil GLCD'yi çalıştıran tüm fonksiyonlar bu dosyada. Dışarıdan kullanılacak etiketler global ile işaretlenmiş durumda. Font etiketini ise extern ile alıp kullanıyorum.

glcd_Font.asm -> İnternetten bulmuş olduğum font verisini saklıyor. Uzunca bir db yığınından oluşan bu listenin etiketi, glcd.asm tarafından kullanılabilmesi için global olarak işaretlenmiş durumda.

glcd.inc -> Header dosyası olması planlanan dosya. glcd.asm içindeki global, tüketici ana programın kullanabilmesi için bu dosyanın başında extern ile tanıtılmış durumda. Ayrıca, makroları da bu dosyaya yazdım. Makrolar glcd.asm içindeki global etiketlerin kullanımını biraz daha kolaylaştırıyor. Bu dosya tüketici ana program tarafından #include edilmek üzere tasarlandı.

glcd_test.asm -> Test amaçlı yazılan tüketici ana program. Ekranda birkaç piksel yakma, çizgi ve çember çizme, ekrana "Tagli" yazma gibi birkaç gereksiz iş yapıyor :) Programın başında "#include glcd.inc" ifadesi bulunuyor.

Ana programın (ve de programcının) kütüphane ile etkileşiminin tamamen glcd.inc dosyası üzerinden yapılabilmesini istediğimden bacak bağlantılarını gösteren #define yığınını glcd.asm'den glcd.inc'e taşımak istiyorum ama bunu yapamadım. Çünkü glcd.asm doğal olarak #define'lar olmadan derlenmiyor. Taşımadan sonra glcd.asm başında "#include glcd.inc" yazınca ise, bu sefer de glcd.inc başındaki extern'li ifadeler yüzünden "duplicate label" hatası alıyorum, ki bu da çok doğal... Ama sorunu nasıl çözeceğimi bulamadım. Sorun önemsiz gibi gözükse de (muhtemelen "Boşver, bacak tanımlamaları da glcd.asm içinde dursun, ne olacak ki?" diyeceksiniz), yazılan şeyin bir kütüphane olması sebebiyle standart bir formatta olmasını istediğimden bu sorun benim için önemli sayılır. Yukarıda da belirttiğim gibi, bir kullanıcı, kütüphane ile etkileşimini tek bir header dosyası üzerinden yapmak ister.
Gökçe Tağlıoğlu

z

Cok basit bir ornek kod verirsen bizde kafa yoralim.

Ornegin asm dosyasinda fonk diye bir label fonksiyonun girisi olsun.
Bu fonksiyon bir iki degiskene erissin vs.

Demek istedigim yapmak istedigin projeyi degil de derlendiginde sorunu ortaya koyacak cok basit bir program parcaciginin inc, asm header dosyalarini yolla.


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

bigbey

TA6R

fahri-

Hocam kendin çalıp kendin oynamıyorsun takip ediyoruz ama sanırım asm kod yazan az olduğu için yorum gelmiyordur.

Tagli

#6
Tamamlanmamış GLCD kütüphanesini buradan indirebilirsiniz. Henüz ince ayar yapılmadığından program bekleme döngüleri 20 MHz için derleniyor. Ayrıca CS bacaklarının 1 iken etkin olduğunu varsaydım, benim üzerinde çalıştığım GLCD'de öyle ama okuduğum kadarıyla tam tersi de olabiliyormuş.

Yapmak istediğim şey, glcd.asm içindeki bacak tanımlamalarını glcd.inc dosyası içine taşıyabilmek. Bunu nasıl yapacağımı bulamadım. Onun dışında hem yukarıdaki iletilerimden okuduğunuz/okuyacağınız kadarıyla, hem de koddan görebileceğiniz gibi rahat kullanılabilir bir kütüphane formatı oluşturduğumu düşünüyorum. İnternette bununla ilgili örnek bulamadığımdan bu işin standartını bilmiyorum, zaten bu başlığı da bunu öğrenmek için açmıştım.

bunalmis hocam, kodun sadeleştirilmiş halini talep etmişsin ama glcd.asm'nin içindeki yoğunluğu saymazsak diğer dosyalar zaten çok rahat anlaşılacak kadar sade. glcd.asm'nin ise önemli olan kısmı zaten baş tarafı. Bu yüzden, fiziksel ortamda çalışan deneme amaçlı bu projeyi olduğu gibi vermeyi uygun gördüm. Zaten projeye biraz daha çeki düzen verince, forumun kütüphane bölümünde ayrıca bir başlıkta paylaşacağım.

Not: Kişisel tercihlerim ve alışkanlıklarım sebebiyle yazdığım kodda tab boyutunu 16 olarak kullanıyorum. Kodu düzgün görebilmeniz açısından aynı ayarı kullanmanız gerekiyor. MPLAB'de "Edit -> Properties -> ASM File Types -> Tab Size" yolunu izlerseniz ilgili ayarı bulabilirsiniz.
Gökçe Tağlıoğlu

Tagli

#7
Arkadaşlar biraz düşündüm, taşındım, kaşındım ve sorunu çözdüm sanırım. Daha doğrusu kesin çözdüm ama çözüm uygun bir formatta mıdır sadece ondan emin değilim.

Hatırlarsanız yukarıda iki şeyi denediğimden bahsetmiştim: Önce bacak bağlantılarını belirleyen #define yığınını glcd.inc içine taşımıştım ve doğal olarak derleme yapılamamıştı. Daha sonra glcd.inc'i aynı zamanda glcd.asm'nin başında da include etmiştim. Bu sefer de glcd.inc içindeki extern olarak işaretlenmiş etiketler zaten glcd.asm'nin etiketleri olduğundan "duplicate label" hatası almıştım.

Yukarıdaki durumdan şu şekilde kurtuldum: Öncelikle glcd.asm'nin başına bir işaret olarak "define #GLCD.ASM" ifadesini ekledim. Daha sonra ise glcd.inc içindeki extern'li ifadeleri ve makroları "ifndef GLCD.ASM ---  endif" arasına yerleştirince, bu bölüm, glcd.inc'i include eden glcd.asm için görünmez hale geldi ve artık hata vermiyor.

Bu yöntemin benzeri aslında C/C++ header dosyalarında kullanılan standart bir yaklaşım. Aynı header dosyasının yanlışlıkla tekrar tekrar include edilmesini engellemek için kod "header guard" denilen bir yapı içine alınır.

Kütüphanenin güncellenmiş halini buradan indirebilirsiniz. Ancak hâlâ tamamlanmamış olduğunu aklınızda bulundurun.

C18 bağlantısının nasıl yapılacağını henüz öğrenebilmiş değilim ama C18'in resmi dökümanında bu konuda bilgi var gibi gözüküyor. O konu bu başlıkla doğrudan ilgili sayılmaz sanırım. Nasıl yapıldığını öğrendiğim zaman onu da bir örnekle (muhtemelen yine GLCD kütüphanesi üzerinden) paylaşırım. İlgilenen arkadaşlara teşekkürler.
Gökçe Tağlıoğlu