ARM işlemcisinin komut setinin incelenmesi. ARM işlemci komut setinin incelenmesi ARM birleştirici talimatlarının örnekleri

GBA ASM - 2. Gün: ARM birleştirici hakkında bazı bilgiler - Arşiv WASM.RU

ARM, GBA işlemcisini üreten şirkettir. ARM işlemcileri RISC işlemcileridir (INTEL işlemcilerinin aksine). RISC, Azaltılmış Komut Seti Bilgisayarları (CISC - Kompleks...) anlamına gelir. Bu işlemciler çok fazla talimata sahip olmasa da (ki bu iyi bir şey), ARM talimatlarının (ve belki diğer RISC işlemcilerin, bilmiyorum) birçok farklı amacı ve kombinasyonu vardır, bu da RISC işlemcilerini bu kadar güçlü kılan şeydir. .

Kayıtlar

Diğer ARM işlemcileri bilmiyorum ama GBA'da kullanılanın 16 kaydı var ve Intel işlemcilerden (ve diğerlerinden) farklı olarak tüm kayıtlar (genellikle) güvenle kullanılabilir. Kayıtlar aşağıdaki gibidir:

r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15

Vay! Birçok! Sırasıyla anlatacağım.

ro: Ne istiyorsan onu yap!

r2 ila r12: aynı

r13: Bazı ARM sistemlerinde r13 bir yığın işaretçisidir (INTEL işlemcilerde SP). R13'ün GBA'da aynı rolü oynayıp oynamadığından emin değilim, sizi yalnızca yığınla çalışırken dikkatli olmanız konusunda uyarabilirim.

r14: Çağrılan prosedürlerin dönüş adresini içerir. Eğer bunları kullanmıyorsanız, onunla istediğinizi yapabilirsiniz.

r15: Program Sayacı ve bayraklar, IP (Intel'deki Talimat İşaretçisi) ile aynıdır. Diğer kayıtlar gibi ücretsiz erişime sahip olmanız açısından Intel'in IP kaydından farklıdır, ancak bunu değiştirmenin kontrolün kodun başka bir bölümüne aktarılmasına neden olacağını ve işaretlerin değişeceğini unutmayın.

Biraz matematik yapalım... 16 eksi 3 (genellikle) bize 13 kayıt verir. Çok hoş değil mi? Sakin ol.

Şimdi kayıtların gerçekte ne olduğunu merak ediyor olabilirsiniz. Kayıtlar, işlemcinin bir parçası olan ve gerçek bir adresi olmayan, yalnızca adlarıyla bilinen özel bellek alanlarıdır. Kayıtlar 32 bittir. Herhangi bir montaj dilindeki hemen hemen her şey yazmaçları kullanır, bu yüzden onları akrabalarınız kadar iyi bilmelisiniz.

ARM montajcı talimatları

Öncelikle ARM montajcısını kim bulduysa bence bir dahi olduğunu söyleyerek başlamak istiyorum.

İkinci olarak yakın arkadaşım CMP'yi tanıtmak istiyorum. Ona selam söyle, belki o da senin arkadaşın olur. CMP, CoMPare (karşılaştırma) anlamına gelir. Bu komut, kayıt ve numarayı, kayıt ve kaydı veya kayıt ve hafıza konumunu karşılaştırabilir. Daha sonra karşılaştırmanın ardından CMP, size karşılaştırmanın sonucunu bildiren durum bayraklarını ayarlar. Hatırlayacağınız gibi r15 saklayıcısı flaglar içermektedir. Karşılaştırmanın sonucunu bildirirler. CMP talimatı, bu bayrakların değerini ayarlamak için özel olarak tasarlanmıştır, başka hiçbir şeyi ayarlamaz.

Bayraklar aşağıdaki durumları içerebilir:

    EQ Eşit / Eşit

    NE Eşit Değil

    VS oVerflow Seti

    VC oVerflow Temizle

    HI Daha yüksek / Daha yüksek

    LS Daha Düşük veya Aynı / Aşağıda veya aynı

    PL Artı / Artı

    MI EKSİ / Eksi

    CS Taşıma Seti

    CC Taşıma Temizle

    GE Büyüktür veya Eşittir / Büyüktür veya eşittir

    GT Büyük / Daha Fazla

    LE Küçüktür veya Eşittir / Küçüktür veya eşittir

    LT Küçük / Az

    Z Sıfır / Sıfırdır

    Yeni Zelanda Sıfır değil / Sıfır değil

Bu durumlar ARM assembler'da çok önemli bir rol oynamaktadır.

NOT: bayraklar yalnızca koşulları saklar (Eşit, Küçüktür vb.). Artık önemli değiller.

Koşul ekleri

B talimatını (Şube) zaten gördünüz. Talimat B, koşulsuz atlama olarak adlandırılan şeyi yapar (Basic'teki GoTo veya INTEL derlemesindeki JMP gibi). Ancak bir son eki olabilir (yukarıda listelenenlerden biri), ardından bayrakların durumunun bununla eşleşip eşleşmediğini kontrol eder. Aksi takdirde atlama talimatı yürütülmez. Dolayısıyla, r0 kaydının r4 kaydına eşit olup olmadığını kontrol etmek ve ardından label34 adlı bir etikete gitmek istiyorsanız aşağıdaki kodu yazmanız gerekir:

    CMP r0, r4; Assembler'da açıklamalar noktalı virgülden (;) sonra gelir

    BEQ etiketi34; B bir atlama talimatıdır ve EQ bir sonek anlamına gelir

    ; "Eşit ise"

NOT: Goldroad Assembler'da etiketlerin yanında ( işaretinin bulunmasına gerek yoktur ve satırda etiket adından başka hiçbir şey olmamalıdır.

NOT II: CMP ve BEQ'nun büyük harfle yazılmasına gerek yoktur, bu sadece sizin için daha anlaşılır hale getirmek içindir.

Artık bayrakların durumuna bağlı olarak nasıl geçiş yapacağınızı biliyorsunuz, ancak bayrakların durumuna bağlı olarak her şeyi yapabileceğinizi bilmiyorsunuz, sadece istediğiniz son eki herhangi bir talimata ekleyin!

Ayrıca bayrakların durumunu ayarlamak için CMP kullanmanıza gerek yoktur. Örneğin SUB (Çıkarma) talimatının bayrakları ayarlamasını istiyorsanız, talimata "S" sonekini ekleyin ("Bayrakları ayarla" anlamına gelir). Bayrakların durumunu ekstra bir CMP talimatıyla ayarlamak istemiyorsanız bu kullanışlıdır; böylece bunu yapabilir ve sonuç şu şekilde sıfırsa atlayabilirsiniz:

    SUBS r0,r1,0x0FF ; Bayrakları yürütme sonucuna göre ayarlar

    ; talimatlar

    ldrZ r0,=0x0FFFF ; R0 kaydını 0x0FFFF ile yalnızca durum aşağıdaki durumlarda yükleyecektir:

    bayraklar Sıfır'a eşittir.

Gözden geçirmek

Bugün kayıtlar hakkında (biraz daha fazla) bilgi edindik. Ayrıca bayrakların durumuna bağlı olarak yürütülebilen (ya da yürütülemeyen) ARM talimatlarının esnekliğini de öğrendik. Bugün çok şey öğrendik.

Yarın, GBA ekranında bir resim görüntülemek için bugün edinilen ARM assembler bilgisini kullanacağız.

İmkansız bir şey ancak mümkün olana kadar öyledir / Jean-Luc Picard, Yüzbaşı. ,USS Enterprise/. Mike H, çev. Aquila

CISC işlemcileri, bellek hücrelerinin içerikleri üzerinde aritmetik ve mantıksal işlemler de dahil olmak üzere oldukça karmaşık işlemleri tek bir komutla gerçekleştirir. CISC işlemci talimatları farklı uzunluklara sahip olabilir.

Buna karşılık, RISC'nin işlem türüne göre net bir şekilde bölünen nispeten basit bir talimat sistemi vardır:

  • Bellekle çalışma (bellekten yazmaçlara okuma veya yazmaçlardan belleğe yazma),
  • kayıtlardaki verilerin işlenmesi (aritmetik, mantıksal, veri sola/sağa kayma veya bir kayıttaki bit dönüşü),
  • diğer adreslere koşullu veya koşulsuz geçiş komutları.

Kural olarak (ancak her zaman değil ve yalnızca program kodu denetleyicinin önbelleğine girdiğinde), bir işlemci döngüsünde bir komut yürütülür. ARM işlemci komutunun uzunluğu sabittir - 4 bayt (bir bilgisayar kelimesi). Aslında modern bir ARM işlemci, talimat uzunluğu 2 bayt olduğunda diğer çalışma modlarına, örneğin THUMB moduna geçebilir. Bu, kodu daha kompakt hale getirmenizi sağlar. Ancak Amber ARM v2a işlemcide desteklenmediğinden bu yazımızda bu modu ele almıyoruz. Aynı nedenden ötürü, Jazelle (Java kodunu yürütmek için optimize edilmiş) gibi modları dikkate almayacağız ve birden fazla veri üzerinde işlemlere yönelik komutlar olan NEON komutlarını dikkate almayacağız. Sonuçta saf ARM talimat sistemini inceliyoruz.

ARM işlemci kayıtları.

ARM işlemcisinin birkaç kayıt seti vardır ve bunlardan yalnızca 16'sı şu anda programcının kullanımına açıktır.Birkaç işlemci çalışma modu vardır, çalışma moduna bağlı olarak uygun kayıt bankası seçilir. Bu çalışma modları:

  • uygulama modu (USR, kullanıcı modu),
  • yönetici modu veya işletim sistemi modu (SVC, yönetici modu),
  • kesme işleme modu (IRQ, kesme modu) ve
  • “acil kesinti” işleme modu (FIRQ, hızlı kesinti modu).

Yani, örneğin bir kesinti meydana geldiğinde işlemcinin kendisi kesme işleyici programının adresine gider ve kayıt bankalarını otomatik olarak "değiştirir".

Eski sürümlerin ARM işlemcileri, yukarıdaki çalışma modlarına ek olarak ek modlara da sahiptir:

  • İptal et (bellek erişimi istisnalarını işlemek için kullanılır),
  • Tanımsız (yazılımda bir yardımcı işlemci uygulamak için kullanılır) ve
  • işletim sistemi sisteminin ayrıcalıklı görev modu.

Amber ARM v2a işlemcide bu ek üç mod yoktur.

Amber ARM v2a için kayıt kümesi şu şekilde temsil edilebilir:

r0-r7 kayıtları tüm modlar için aynıdır.
R8-r12 kayıtları yalnızca USR, SVC, IRQ modları için ortaktır.
R13 kaydı bir yığın işaretçisidir. O, her halükarda kendisine aittir.
Kayıt r14 - alt programdan dönüş kaydı da tüm modlarda farklıdır.
R15 kaydı yürütülebilir talimatların bir işaretçisidir. Tüm modlar için ortaktır.

FIRQ modunun en izole olduğu, kendi kayıtlarının çoğuna sahip olduğu görülebilir. Bu, bazı çok kritik kesintilerin, yığındaki kayıtları kaydetmeden, zaman kaybetmeden işlenebilmesi için yapılır.

Yürütülebilir komutların işaretçisi olan pc (Program Sayacı) olarak da bilinen r15 kaydına özellikle dikkat edilmelidir. İçeriği üzerinde çeşitli aritmetik ve mantıksal işlemler gerçekleştirebilirsiniz, böylece programın yürütülmesi diğer adreslere taşınacaktır. Ancak özellikle Amber sisteminde uygulanan ARM v2a işlemci için bu kaydın bitlerinin yorumlanmasında bazı incelikler vardır.

Gerçek şu ki, bu işlemcide, r15 (pc) kaydında, yürütülebilir komutların gerçek işaretçisine ek olarak aşağıdaki bilgiler de bulunur:

Bit 31:28 - aritmetik veya mantıksal bir işlemin sonucunu gösteren işaretler
Bit 27 - kesme IRQ maskesi, bit ayarlandığında kesmeler devre dışı bırakılır.
Bit 26 - FIRQ kesme maskesi, bit ayarlandığında hızlı kesmeler devre dışı bırakılır.
Bit 25:2 - program talimatlarına yönelik gerçek işaretçi yalnızca 26 bit kaplar.
Bitler 1:0 - geçerli işlemci çalışma modu.
3 - Süpervizör
2 - Kesinti
1 - Hızlı Kesinti
0 - Kullanıcı

Eski ARM işlemcilerde tüm bayraklar ve hizmet bitleri ayrı kayıtlarda bulunur Mevcut Program Durum Kaydı(cpsr) ve Kayıtlı Program Durumu Kaydı (spsr), erişim için ayrı özel komutların bulunduğu. Bu, programlar için kullanılabilir adres alanını genişletmek amacıyla yapılır.

ARM assembler'da uzmanlaşmanın zorluklarından biri bazı kayıtların alternatif isimleridir. Yani yukarıda da belirtildiği gibi r15 aynı bilgisayardır. Ayrıca r13 de vardır - bu aynı sp'dir (Yığın İşaretçisi), r14, lr'dir (Bağlantı Kaydı) - prosedürden dönüş adresi kaydıdır. Ek olarak, r12, C derleyicileri tarafından yığındaki parametrelere erişmek için özel bir şekilde kullanılan aynı IP'dir (Prosedür İçi -çağrı karalama kaydı). Bu tür alternatif adlandırma bazen başka birinin program koduna baktığınızda kafa karıştırıcı olabilir - bu kayıt adlarının her ikisi de orada bulunur.

Kod yürütmenin özellikleri.

Pek çok işlemci türünde (örneğin x86) koşula bağlı olarak yalnızca başka bir program adresine geçiş gerçekleştirilebilir. ARM'da durum böyle değil. Her ARM işlemci talimatı koşullu olarak yürütülebilir veya yürütülmeyebilir. Bu, programdaki geçiş sayısını en aza indirmenize ve dolayısıyla işlemci hattını daha verimli kullanmanıza olanak tanır.

Sonuçta boru hattı nedir? Şimdi program kodundan bir işlemci talimatı seçilir, öncekinin kodu zaten çözülmektedir ve öncekinin zaten yürütülmektedir. Bu, Mars Rover2Mars Rover2 kartı için projemizde kullandığımız Amber A23 işlemcisinin 3 aşamalı boru hattının durumudur. Amber A25 işlemcinin modifikasyonu 5 aşamalı bir boru hattına sahiptir, daha da verimlidir. Ancak büyük bir AMA var. Atlama komutları işlemciyi boru hattını temizlemeye ve yeniden doldurmaya zorlar. Böylece, yeni bir komut seçilir, ancak hala kodu çözülecek hiçbir şey yoktur ve dahası, hemen yürütülecek hiçbir şey yoktur. Kod yürütmenin verimliliği sık geçişlerle azalır. Modern işlemciler, boru hattının doldurulmasını bir şekilde optimize eden her türlü dallanma tahmin mekanizmasına sahiptir, ancak bizim işlemcimizde bu yoktur. Her durumda, ARM her komutun koşullu olarak yürütülmesini mümkün kılmak konusunda akıllıca davrandı.

Bir ARM işlemcide, herhangi bir talimat türünde, talimat yürütme koşulunun dört biti, talimat kodunun en yüksek dört bitinde kodlanır:

İşlemcide toplam 4 durum bayrağı vardır:
. Negatif - operasyonun sonucu negatifti,
. Sıfır - sonuç sıfırdır,
. Taşıma - imzasız numaralarla bir işlem gerçekleştirilirken bir taşıma meydana geldi,
. oVerflow - imzalı sayılarla işlem yapılırken taşma oluştu, sonuç kayıt defterine uymuyor)

Bu 4 bayrak birçok olası durum kombinasyonunu oluşturur:

Kod son ek Anlam Bayraklar
4"sa0 eşitlik Eşit Z seti
4"h1 hayır Eşit değil Z temizle
4"h2 cs/hs Taşıma seti / imzasız daha yüksek veya aynı C seti
4"h3 cc/lo Şeffaf / imzasız alt taşıyın Temizle
4"h4 mi Eksi/negatif N seti
4"h5 lütfen Artı / pozitif veya sıfır N temizle
4"h6 vs Taşma V seti
4"h7 vc Taşma yok V temizle
4"h8 MERHABA İmzasız daha yüksek C seti ve Z temizle
4"h9 ls İmzasız alt veya aynı C temizle veya Z seti
4" ha ge Büyük veya eşittir olarak imzalanmış N == V
4" hb lt Şundan daha az imzalandı: N != V
4"hc GT Şundan daha büyük imzalandı: Z == 0,N == V
4"HD le Daha az veya eşit olarak imzalanmış Z == 1 veya N != V
4"o al Her zaman (koşulsuz)
4"hf - Geçersiz koşul

Bu da ARM işlemci talimatlarını öğrenmede başka bir zorluğa yol açıyor; talimat koduna eklenebilecek çok sayıda son ek. Örneğin, Z bayrağının ayarlanması koşuluyla ekleme, add + sonek eq olarak addeq komutudur. N=0 bayrağı bl + pl son eki olarak blpl ise alt programa atlayın.

Bayraklar (Negatif, Sıfır, Taşıma, Taşma) aynı şey, örneğin bir x86 işlemcide olduğu gibi, aritmetik veya mantıksal işlemler sırasında her zaman ayarlanmaz, yalnızca programcı istediğinde ayarlanır. Bunun için komut anımsatıcılarına başka bir ek daha vardır: “s” (komut kodunda bit 20 ile kodlanmıştır). Bu nedenle, ekleme komutu bayrakları değiştirmez, ancak ekleme komutu bayrakları değiştirir. Veya koşullu bir ekleme komutu da olabilir, ancak bu komut bayrakları değiştirir. Örneğin: eklentiler. Koşullu yürütme ve bayrakları ayarlamak için farklı son eklere sahip komut adlarının olası kombinasyonlarının sayısının, bir ARM işlemcisinin montaj kodunu çok tuhaf ve okunması zor hale getirdiği açıktır. Ancak zamanla alışırsınız ve bu metni anlamaya başlarsınız.

Aritmetik ve mantıksal işlemler (Veri İşleme).

ARM işlemcisi çeşitli aritmetik ve mantıksal işlemleri gerçekleştirebilir.

Gerçek dört bitlik işlem kodu (Opcode), işlemci talimat bitlerinde bulunur.

Kaydının içeriği ve değiştiren_işleneni üzerinde herhangi bir işlem gerçekleştirilir. İşlemin sonucu kayıt defterine yerleştirilir. Dört bitlik Rn ve Rd, işlemcinin aktif kümesindeki kayıtların indeksleridir.

I 25 bitine bağlı olarak, Shifter_operand ya sayısal bir sabit olarak ya da işlenenin ikinci yazmacının bir dizini olarak ve hatta ikinci işlenenin değeri üzerinde bir kaydırma işlemi olarak ele alınır.

Montajcı komutlarının basit örnekleri şöyle görünecektir:

r0,r1,r2 ekleyin @ r1 ve r2 yazmaçlarının değerlerinin toplamını r0 yazmacına yerleştirin
sub r5,r4,#7 @ farkı (r4-7) r5 yazmacına yerleştirin

Yapılan işlemler şu şekilde kodlanmıştır:

4"h0 ve Mantıksal VE Rd:= Rn VE değiştiren_işlenen
4"h1 eor Mantıksal özel OR Rd:= Rn XOR değiştiren_işlenen
4"h2 alt Aritmetik çıkarma Rd:= Rn - değiştiren_işlenen
4"h3 rsb Aritmetik ters çıkarma Rd:= değiştiren_işlenen - Rn
4"h4 Aritmetik toplamayı ekle Rd:= Rn + değiştiren_işlenen
4"h5 adc Aritmetik toplama artı taşıma bayrağı Rd:= Rn + Shifter_operand + Taşıma Bayrağı
4"h6 sbc Taşıma ile aritmetik çıkarma Rd:= Rn - değiştiren_işlenen - NOT(Taşıma Bayrağı)
4"h7 rsc Taşıma ile aritmetik ters çıkarma Rd:= değiştiren_işlenen - Rn - NOT(Taşıma Bayrağı)
4"h8 tst Mantıksal AND, ancak sonucu kaydetmeden, yalnızca her zaman ayarlanan Rn AND Shifter_operand S bit bayrakları değiştirilir
4"h9 teq Mantıksal özel OR, ancak sonucu kaydetmeden yalnızca Rn EOR Shifter_operand işaretleri değiştirilir
S biti her zaman ayarlanır
4"ha cmp Karşılaştırma veya sonucu kaydetmeden aritmetik çıkarma, yalnızca Rn bayrakları değişir -shifter_operand S biti her zaman ayarlanır
4"hb cmn Ters veya daha doğrusu aritmetik toplamanın sonucu saklamadan karşılaştırılması, yalnızca Rn + Shifter_operand S bit bayrakları her zaman değişikliği ayarlar
4"hc orr Mantıksal VEYA Rd:= Rn VEYA kaydırıcı_işlenen
4"hd mov Kopya değeri Rd:= Shifter_operand (ilk işlenen yok)
4"he bic Bitleri sıfırla Rd:= Rn AND NOT(shifter_operand)
4"hf mvn Ters değeri kopyala Rd:= Shifter_operand DEĞİL (ilk işlenen yok)

Namlu değiştirici.

ARM işlemcisi, herhangi bir aritmetik veya mantıksal işlemden önce işlenenlerden birinin belirli sayıda bit kadar kaydırılmasına veya döndürülmesine olanak tanıyan özel bir "varil kaydırma" devresine sahiptir. Bu, işlemcinin oldukça verimli bir kod oluşturmanıza olanak tanıyan oldukça ilginç bir özelliğidir.

Örneğin:

@9 ile çarpmak bir sayıyı 8 ile çarpmak demektir
@ 3 bit artı başka bir sayı sola kaydırarak
r0, r1, r1, lsl #3'ü ekle @ r0= r1+(r1<<3) = r1*9

@ 15 ile çarpmak, 16 eksi sayı ile çarpmak demektir
rsb r0, r1, r1, lsl #4 @ r0= (r1<<4)-r1 = r1*15

@ 4 baytlık kelimelerden oluşan bir tabloya erişim;
@r1 tablonun temel adresidir
@r2 tablodaki öğenin indeksidir
ldr r0,

Mantıksal sola kaydırma lsl'ye ek olarak, mantıksal sağa kaydırma lsr ve aritmetik sağa kaydırma asr de vardır (işareti koruyan kaydırma, en anlamlı bit kaydırmayla eş zamanlı olarak solda çarpılır).

Ayrıca yuvarlak uçların dönüşü de vardır; uçlar sağa doğru hareket eder ve dışarı çekilenler sola doğru hareket eder.
C bayrağı aracılığıyla bir bitlik kayma vardır - bu rrx komutudur. Kayıt değeri bir bit sağa kaydırılır. Sol tarafta, C bayrağı yazmacın en anlamlı bitine yüklenir.

Kaydırma, sabit bir sabit sayı ile değil, üçüncü işlenen yazmacının değeri ile gerçekleştirilebilir. Örneğin:

r0, r1, r1, lsr r3'ü ekle @ bu r0 = r1 + (r1>>r3);
r0, r0, r1, lsr r3'ü ekle @ bu r0 = r0 + (r1>>r3);

Yani Shifter_operand, assembler komutlarında tanımladığımız şeydir; örneğin "r1, lsr r3" veya "r2, lsl #5".

En ilginç şey, operasyonlardaki vardiyaları kullanmanın hiçbir maliyeti olmamasıdır. Bu geçişler (genellikle) ek saat döngüleri gerektirmez, bu da sistem performansı için çok iyidir.

Sayısal işlenenlerin kullanılması.

Aritmetik veya mantıksal işlemler yalnızca bir yazmacın içeriğini değil aynı zamanda ikinci işlenen olarak sayısal bir sabiti de kullanabilir.

Ne yazık ki burada önemli bir sınırlama var. Tüm komutların sabit uzunluğu 4 bayt (32 bit) olduğundan, içinde "herhangi bir" sayının kodlanması mümkün olmayacaktır. İşlem kodunda, 4 bit zaten yürütme koşulu kodu (Cond) tarafından, 4 bit işlem kodunun kendisi için (Opcode), ardından 4 bit - alıcı kaydı Rd ve diğer 4 bit - ilk işlenenin kaydı tarafından işgal edilmiştir. Rn, artı çeşitli bayraklar I 25 (sadece işlem kodundaki sayısal bir sabiti belirtir) ve S 20 (işlemden sonra bayrakların ayarlanması). Toplamda, olası bir sabit için yalnızca 12 bit kaldı, sözde Shifter_operand - bunu yukarıda gördük. 12 bit yalnızca dar bir aralıktaki sayıları kodlayabildiğinden, ARM işlemcinin geliştiricileri sabiti aşağıdaki gibi kodlamaya karar verdiler. Shifter_operand'ın on iki biti iki bölüme ayrılmıştır: dört bitlik dönüş göstergesi encode_imm ve gerçek sekiz bitlik sayısal değer imm_8.

Bir ARM işlemcide sabit, 32 bitlik bir sayının içinde, çift sayıda bitle sağa döndürülmüş sekiz bitlik bir sayı olarak tanımlanır. Yani:

imm_32 = imm_8 ROR (encode_imm *2)

Oldukça zor çıktı. Assembler komutlarında her sabit sayının kullanılamayacağı ortaya çıktı.

Yazabilirsin

ondalık biçimde r0, r2, #255 @ sabitini ekleyin
onaltılık sistemde r0, r3, #0xFF @ sabitini ekleyin

255 8 bit aralığında olduğundan. Bu komutlar şu şekilde derlenecektir:

0: e28200ff r0, r2, #255'i ekle; 0xff
4: e28300ff r0, r3, #255'i ekleyin; 0xff

Ve hatta yazabilirsin

r0, r4, #512'yi ekle
r0, r5, 0x650000'i ekle

Derlenen kod şöyle görünecek:

0: e2840c02 ekle r0, r4, #512 ; 0x200
4: e2850865 r0, r5, #6619136'yı ekleyin; 0x650000

Bu durumda 512 sayısının kendisi elbette bayta sığmıyor. Ama sonra onu onaltılık biçimde 32'h00000200 olarak hayal ediyoruz ve bunun 2 sağa doğru 24 bit (1 veya 24) genişletilmiş olduğunu görüyoruz. Dönme katsayısı 24'ten iki kat daha azdır, yani 12. Yani ortaya çıkıyor Shifter_operand = ( 4'hc , 8'h02 ) - bunlar komutun en az on iki bitidir. Aynı şey 0x650000 sayısı için de geçerli. Onun için, değiştiren_işlenen = ( 4'h8, 8'h65 ).

Yazamayacağın çok açık

r0, r1,#1234567 ekle

yoksa yazamazsın

hareket r0, #511

çünkü burada sayı imm_8 ve encode_imm - dönüş faktörü biçiminde temsil edilemez. Montajcı derleyicisi bir hata verecektir.

Bir sabit doğrudan Shifter_operand'a kodlanamadığında ne yapılmalı? Her türlü numarayı yapmamız gerekecek.
Örneğin, önce 512 sayısını ücretsiz bir kayda yükleyebilir ve ardından bir tane çıkarabilirsiniz:

hareket r0, #511
alt r0,r0,#1

Belirli bir sayıyı bir kayda yüklemenin ikinci yolu, onu bellekte bulunan özel olarak ayrılmış bir değişkenden okumaktır:

ldr r7,my_var
.....
my_var: .word 0x123456

Bunu yazmanın en kolay yolu şu şekildedir:

ldr r2,=511

Bu durumda ("=" işaretine dikkat edin), eğer sabit imm_8 ve encode_imm olarak temsil edilebiliyorsa, eğer Shifter_operand'ın 12. bitine sığabiliyorsa, montaj derleyicisi ldr'yi otomatik olarak bir mov talimatına derleyecektir. Ancak sayı bu şekilde temsil edilemiyorsa derleyicinin kendisi programda bu sabit için bir bellek hücresi ayıracak ve bu bellek hücresine kendisi bir isim verecek ve komutu ldr biçiminde derleyecektir.

Ben şunu yazdım:

ldr r7,my_var
ldr r8,=511
ldr r8,=1024
ldrr9,=0x3456
........
My_var: .word 0x123456

Derlemeden sonra şunu anladım:

18: e59f7030 ldrr7, ; 50
1c: e59f8030 ldr r8, ; 54
20: e3a08b01 mov r8, #1024 ; 0x400
24: e59f902c ldrr9, ; 58
.............
00000050 :
50: 00123456 .word 0x00123456
54: 000001ff .word 0x000001ff
58: 00003456 .word 0x00003456

Derleyicinin bilgisayar kaydına (diğer adıyla r15) göre bellek adresleme kullandığını unutmayın.

Bellek hücresini okumak ve belleğe kayıt yazmak.

Yukarıda da yazdığım gibi ARM işlemcisi, yazmaçların içerikleri üzerinde yalnızca aritmetik veya mantıksal işlemler gerçekleştirebilmektedir. İşlemlere ilişkin veriler bellekten okunmalı ve işlem sonuçları tekrar belleğe yazılmalıdır. Bunun için özel komutlar vardır: okuma için ldr (muhtemelen "LoaD Register" kombinasyonundan) ve yazma için str (muhtemelen "STore Register").

Görünüşe göre sadece iki takım var, ama aslında birçok varyasyonları var. Kaç tane yardımcı bayrak bitinin L 20, W 21, B 22, U 23, P 24, I 25 olduğunu görmek için Amber ARM işlemcide ldr /str komutlarının kodlanma şekline bakın ve bunlar, komuta:

  • Bit L 20 yazmayı veya okumayı belirler. 1 - ldr, oku, 0 - str, yaz.
  • Bit B 22, 32 bitlik bir kelimenin veya 8 bitlik bir baytın okuma/yazma işlemini belirler. 1 bayt işlemi anlamına gelir. Bir bayt bir kayda okunduğunda, kaydın en önemli bitleri sıfıra sıfırlanır.
  • Bit I 25 Ofset alanının kullanımını belirler. I 25 ==0 ise, Ofset, kayıttan temel adrese eklenmesi veya çıkarılması gereken sayısal bir ofset olarak yorumlanır. Ancak ekleme veya çıkarma işlemi U 23 bitine bağlıdır.

(Koşul) - işlemi gerçekleştirme koşulu. Mantıksal/aritmetik komutlarla aynı şekilde yorumlanır; okuma veya yazma koşullu olabilir.

Böylece, montaj metninde şöyle bir şey yazabilirsiniz:

ldr r1, @ r1 kaydına girer, r0 kaydından adresteki kelimeyi okur
ldrb r1, @ r1 kaydına girer, r0 kaydından adresteki baytı okur
ldreq r2, @ koşullu kelime okuma
ldrgtb r2, @ koşullu bayt okuma
ldr r3, @ r4 kaydındaki adrese göre adres 8'deki kelimeyi oku
ldr r4, @ r5 kaydındaki adrese göre -16 adresindeki kelimeyi oku

Bu metni derledikten sonra bu komutların gerçek kodlarını görebilirsiniz:

0: e5901000 ldr r1,
4: e5d01000 ldrb r1,
8: 05912000 ldreq r2,
c: c5d12000 ldrbgt r2,
10: e5943008 ldr r3,
14: e5154010 ldr r4,

Yukarıdaki örnekte yalnızca ldr kullanıyorum ancak str hemen hemen aynı şekilde kullanılıyor.

İndeks öncesi ve indeks sonrası geri yazma belleği erişim modları vardır. Bu modlarda, bellek erişim işaretçisi talimatın yürütülmesinden önce veya sonra güncellenir. C programlama diline aşinaysanız, ( gibi) işaretçi erişim yapılarına da aşinasınız demektir. *psource++;) veya ( a=*++pkaynak;). ARM işlemci bu bellek erişim modunu uygular. Bir okuma komutu yürütüldüğünde, iki kayıt aynı anda güncellenir - alıcı kaydı bellekten okunan değeri alır ve işaretçi kaydındaki değer bellek hücresine ileri veya geri taşınır.

Bu komutları yazmak bence biraz mantıksız. Alışmak uzun zaman alıyor.

ldr r3, ! @psrc++; r3 = *psrc;
ldr r3, , #4 @ r3 = *psrc; psrc++;

İlk ldr komutu önce işaretçiyi artırır, ardından okur. İkinci komut önce işaretçiyi okur, ardından artırır. psrc işaretçisinin değeri r0 yazmacındadır.

Yukarıda tartışılan örneklerin tümü, komut kodundaki bit I 25'in sıfırlandığı durum içindir. Ancak yine de kurulabilir! O zaman Ofset alanının değeri sayısal bir sabit değil, işleme katılan üçüncü kaydı içerecektir. Üstelik üçüncü kaydın değeri hâlâ önceden kaydırılabilir!

Aşağıda olası kod varyasyonlarına örnekler verilmiştir:

0: e7921003 ldr r1, @ okuma adresi - r2 ve r3 kayıtlarındaki değerlerin toplamı
4: e7b21003 ldr r1, ! @ aynı, ancak r2'yi okuduktan sonra r3'teki değer kadar artırılacak
8: e6932004 ldr r2, , r4 @ önce r3 adresinde okuma yapılacak, ardından r3 r4 oranında artacak
c: e7943185 ldr r3, @ okuma adresi r4+r5*8
10: e7b43285 ldr r3, ! @ okuma adresi r4+r5*32, r4 okunduktan sonra bu adresin değerine ayarlanacaktır
14: e69431a5 ldr r3, , r5, lsr #3 @ r4'ü okumak için adres, komut yürütüldükten sonra r4, r4+r5/8 olarak ayarlanacaktır

Bunlar ARM v2a işlemcisindeki okuma/yazma komutlarının çeşitleridir.

ARM işlemcilerin eski modellerinde bu komut çeşitliliği daha da fazladır.
Bunun nedeni, işlemcinin örneğin yalnızca kelimeleri (32 bit sayılar) ve baytları değil aynı zamanda yarım kelimeleri de (16 bit, 2 bayt) okumaya izin vermesidir. Daha sonra ldr/str komutlarına yarım kelimeden gelen “h” eki eklenir. Komutlar ldrh veya strh gibi görünecektir. Ayrıca, işaretli sayılar olarak yorumlanan yarım sözcükleri ldrsh veya bayt ldrsb'yi yüklemek için komutlar da vardır. Bu durumlarda, yüklenen sözcük veya baytın en anlamlı biti, alıcı kaydındaki tüm sözcüğün en anlamlı bitleriyle çarpılır. Örneğin, 0xff25 yarım sözcüğünün hedef kayıt defterine ldrsh komutuyla yüklenmesi 0xffffff25 ile sonuçlanır.

Çoklu okuma ve yazma.

Belleğe erişim için kullanılanlar yalnızca ldr /str komutları değildir. ARM işlemcisinde ayrıca blok aktarımları gerçekleştirmenize izin veren komutlar bulunur - birkaç ardışık kelimenin içeriğini bellekten ve birkaç kayıttan aynı anda yükleyebilirsiniz. Ayrıca birkaç kaydın değerlerini sıralı olarak belleğe yazabilirsiniz.

Blok aktarım komutu anımsatıcıları kök ldm (LoaD Multiple) veya stm (Store Multiple) ile başlar. Ama sonra ARM'de her zaman olduğu gibi soneklerle ilgili hikaye başlıyor.

Genel olarak komut şöyle görünür:

işlem(koşul)(mod) Rd(, {Register list} !}

(Cond) son eki anlaşılabilir, bu, komutun yürütülmesi için bir koşuldur. Son ek (mod) iletim modudur, buna daha sonra değineceğiz. Rd, okuma veya yazma için bellekteki temel adresi belirleyen bir kayıttır. Rd kaydının ardından gelen ünlem işareti, okuma/yazma işleminden sonra değiştirileceğini gösterir. Bellekten yüklenen veya belleğe çağrılan kayıtların listesi (Kayıt listesi)'dir.

Kayıtların listesi, virgülle ayrılmış küme parantezleri veya aralık olarak belirtilir. Örneğin:

stm r0,(r3,r1, r5-r8)

Bellek sıra dışı olarak yazılacaktır. Liste sadece belleğe hangi kayıtların yazılacağını gösterir ve bu kadar. Komut kodu, tam olarak işlemci kümesindeki kayıt sayısı kadar olan Kayıt Listesi için ayrılmış 16 bit içerir. Bu alandaki her bit, işleme hangi kaydın katılacağını belirtir.

Şimdi okuma/yazma moduna geçelim. Burada kafa karışıklığına yer var. Gerçek şu ki, aynı eylem için farklı mod adları kullanılabilir.

Küçük bir lirik ara söz yaparsak, o zaman yığın hakkında konuşmamız gerekir. Yığın, LIFO türü verilere erişmenin bir yoludur - Son Giren İlk Çıkar (wiki) - son giren ilk çıkar. Yığın, programlamada, prosedürleri çağırırken ve işlevlerin girişinde kayıtların durumunu kaydederken ve çıkışta bunları geri yüklerken ve ayrıca çağrılan prosedürlere parametreler aktarırken yaygın olarak kullanılır.

Kimin aklına gelirdi ki, dört tür hafıza yığını vardır.

İlk tür Tam Azalandır. Bu, yığın işaretçisinin dolu bir yığın öğesine işaret ettiği ve yığının azalan adreslere doğru büyüdüğü zamandır. Yığına bir kelime koymak gerektiğinde önce yığın işaretçisi azaltılır (Önce Azal), ardından sözcük yığın işaretçisinin adresine yazılır. Bir bilgisayar kelimesini yığından kaldırmanız gerektiğinde, kelime yığın işaretçisinin geçerli değeri kullanılarak okunur, ardından işaretçi yukarı hareket eder (Sonra Artış).

İkinci tip Tam Artandır. Yığın aşağı doğru değil, daha büyük adreslere doğru yukarı doğru büyür. İşaretçi aynı zamanda işgal edilen öğeyi de işaret eder. Yığına bir kelime koymanız gerektiğinde önce yığın işaretçisi artırılır, ardından sözcük işaretçiye yazılır (Önce Arttırma). Yığından çıkarmanız gerektiğinde, önce yığın işaretçisini okursunuz, çünkü bu dolu bir öğeye işaret eder, ardından yığın işaretçisi azalır (Sonra Azalır).

Üçüncü tür ise Boş Azalan'dır. Yığın, Tam Azalan durumunda olduğu gibi aşağı doğru büyür, ancak aradaki fark, yığın işaretçisinin boş bir hücreyi işaret etmesidir. Böylece yığına bir kelime koymanız gerektiğinde hemen giriş yapılır, ardından yığın işaretçisi azaltılır (Sonra Azalır). Yığından çıkarırken işaretçi önce artırılır, ardından okunur (Önce Arttırma).

Dördüncü tip Boş Artandır. Umarım her şey açıktır - yığın yukarı doğru büyür. Yığın işaretçisi boş bir öğeye işaret eder. Yığına koymak, yığın işaretçisinin adresine bir kelime yazmak ve yığın işaretçisini artırmak (Sonra Artış) anlamına gelir. Yığından aç - yığın işaretçisini azaltın ve sözcüğü okuyun (Önce Azalt).

Bu nedenle, yığın üzerinde işlemler gerçekleştirirken, yığının türüne bağlı olarak belleğe okuma/yazma işleminden önce veya sonra (Önce/Sonra) işaretçiyi - (Arttırma/Azaltma) artırmanız veya azaltmanız gerekir. Örneğin Intel işlemcilerin yığınla çalışmaya yönelik PUSH (yığına bir sözcük koy) veya POP (yığından bir sözcük çıkar) gibi özel komutları vardır. ARM işlemcisinde özel bir komut bulunmamakla birlikte ldm ve stm komutları kullanılmaktadır.

Yığını ARM işlemci talimatlarını kullanarak uygularsanız aşağıdaki resmi elde edersiniz:

Aynı takıma neden farklı isimler verilmesi gerekti? Hiç anlamıyorum... Burada tabi ki ARM için stack standardının hala Tam Azalan olduğunu da belirtmek gerekiyor.

ARM işlemcideki yığın işaretçisi sp veya r13 kaydıdır. Bu genellikle bir anlaşmadır. Elbette stm yazma veya ldm okuma diğer base kaydedicilerle de yapılabilir. Bununla birlikte, sp kaydının diğer kayıtlardan ne kadar farklı olduğunu hatırlamanız gerekir - farklı işlemci çalışma modlarında (USR, SVC, IRQ, FIRQ) farklı olabilir çünkü bunların kendi kayıt bankaları vardır.

Ve bir not daha. ARM montaj koduna buna benzer bir satır yazın itin (r0-r3), Tabi ki yapabilirsin. Sadece gerçekte aynı takım olacak stmfd sp!,(r0-r3).

Son olarak montaj kodu ve onun derlenmiş demonte metnine bir örnek vereceğim. Sahibiz:


stmfd sp!,(r0-r3)
stmdb sp!,(r0-r3)
itin (r0-r3)

@bu üç talimat aynıdır ve aynı şeyi yapar
açılır(r0-r3)
ldmia sp!,(r0-r3)
ldmfd r13!,(r0-r3)

Stmfd r4,(r0-r3,r5,r8)
stmea r4!,(r0-r3,r7,r9,lr,pc)
ldm r5,(r0,pc)

Derlemeden sonra şunu elde ederiz:

0: e92d000f itme (r0, r1, r2, r3)
4: e92d000f tuşuna basın (r0, r1, r2, r3)
8: e92d000f tuşuna basın (r0, r1, r2, r3)
c: e8bd000f pop (r0, r1, r2, r3)
10: e8bd000f açılır (r0, r1, r2, r3)
14: e8bd000f açılır (r0, r1, r2, r3)
18: e904012f stmdb r4, (r0, r1, r2, r3, r5, r8)
1c: e8a4c28f stmia r4!, (r0, r1, r2, r3, r7, r9, lr, pc)
20: e8958001 ldm r5, (r0, pc)

Programlarda geçişler.

Geçişler olmadan programlama mümkün değildir. Herhangi bir programda, kodun döngüsel olarak yürütülmesi, prosedür ve işlevlerin çağrılması ve ayrıca kod bölümlerinin koşullu olarak yürütülmesi vardır.

Amber ARM v2a işlemcinin yalnızca iki komutu vardır: b (Dal - dal, geçiş kelimesinden) ve bl (Bağlantılı Dal - dönüş adresini korurken geçiş).

Komutun sözdizimi çok basittir:

b(koşul)etiketi
bl(koşul)etiketi

Herhangi bir geçişin koşullu olabileceği açıktır, yani program, “b” ve “bl” köklerinden ve koşul eklerinden (Cond) oluşan buna benzer tuhaf kelimeler içerebilir:

beq, bne, bcs, bhs, bcc, blo, bmi, bpl, bvs, bvc, bhi, bls, bge, bgt, ble, bal, b

bleq, blne, blcs, blhs, blcc, bllo, blmi, blpl, blvs, blvc, blhi, blls, blge, blgt, blle, blal, bl

Çeşitlilik muhteşem, değil mi?

Atlama komutu 24 bitlik bir Ofset içerir. Atlama adresi, bilgisayar işaretçisinin mevcut değeri ile 2 bit sola kaydırılan Ofset numarasının toplamı olarak hesaplanır ve işaretli bir sayı olarak yorumlanır:

Yeni bilgisayar = bilgisayar + Ofset*4

Böylece geçiş aralığı ileri veya geri 32MB olur.

Dönüş adresi bl'yi koruyarak geçişin ne olduğuna bakalım. Bu komut altprogramları çağırmak için kullanılır. Bu komutun ilginç bir özelliği, prosedür çağrılırken prosedürden gelen dönüş adresinin Intel işlemcilerde olduğu gibi yığında değil, normal r14 kaydında saklanmasıdır. Daha sonra prosedürden geri dönmek için, aynı Intel işlemcilerde olduğu gibi özel bir ret komutuna ihtiyacınız yoktur, ancak r14'ün değerini bilgisayara geri kopyalayabilirsiniz. Artık r14 kaydının neden lr (Bağlantı Kaydı) alternatif ismine sahip olduğu açık.

Amber SoC için merhaba dünya projesindeki bayt dışı prosedüre bakalım.

000004a0<_outbyte>:
4a0: e59f1454 ldr r1, ; 8fc< адрес регистра данных UART >
4a4: e59f3454 ldrr3, ; 900< адрес регистра статуса UART >
4a8: e5932000 ldr r2, ; mevcut durumu oku
4ac: e2022020 ve r2, r2, #32
4b0: e3520000 cmp r2, #0 ; UART'ın meşgul olmadığını kontrol edin
4b4: 05c10000 strbeq r0, ; UART'a yalnızca meşgul değilse bir karakter yazın
4b8: 01b0f00e movseq bilgisayarı, lr ; UART'ın meşgul olmaması durumunda prosedürden koşullu dönüş
4bc: 1affff9 bne 4a8<_outbyte+0x8>; UART durumunu kontrol etmek için döngü

Bu parçadaki yorumlardan bu prosedürün nasıl çalıştığının açık olduğunu düşünüyorum.

Geçişlerle ilgili bir diğer önemli not. Kayıtçı r15 (pc), sıradan aritmetik veya mantıksal işlemlerde alıcı kaydı olarak kullanılabilir. Yani add pc,pc,#8 gibi bir komut, başka bir adrese geçmek için tam bir talimattır.

Geçişlerle ilgili bir hatırlatma daha yapmak gerekiyor. Daha eski ARM işlemcilerde ayrıca bx, blx ve blj ek dallanma talimatları bulunur. Bunlar farklı bir komut sistemiyle kod parçalarına atlamak için kullanılan komutlardır. Bx /blx ARM işlemcilerin 16 bitlik THUMB koduna geçiş yapmanızı sağlar. Blj, Jazelle talimat sistemi prosedürlerine (ARM işlemcilerde Java dili desteği) yapılan bir çağrıdır. Amber ARM v2a'mızda bu komutlar yoktur.

Herkese selam!
Mesleğim gereği Java programcısıyım. Son aylardaki çalışmalarım beni Android NDK için geliştirme ve buna bağlı olarak C'de yerel uygulamalar yazma konusunda bilgi sahibi olmaya zorladı. Burada Linux kitaplıklarını optimize etme sorunuyla karşı karşıya kaldım. Birçoğunun ARM için tamamen optimize edilmemiş olduğu ve işlemciyi ağır şekilde yüklediği ortaya çıktı. Daha önce neredeyse hiç montaj dilinde programlama yapmamıştım, bu yüzden ilk başta bu dili öğrenmeye başlamak zordu ama yine de denemeye karar verdim. Bu makale, tabiri caizse, yeni başlayanlar için yeni başlayanlardan yazılmıştır. Zaten öğrendiğim temel bilgileri anlatmaya çalışacağım, umarım bu birilerinin ilgisini çeker. Ayrıca profesyonellerden yapıcı eleştiriler almaktan memnuniyet duyacağım.

giriiş
Öncelikle ARM'ın ne olduğunu bulalım. Wikipedia şu tanımı veriyor:

ARM mimarisi (Gelişmiş RISC Makinesi, Acorn RISC Makinesi, gelişmiş RISC makinesi), ARM Limited tarafından geliştirilen lisanslı 32 bit ve 64 bit mikroişlemci çekirdeklerinden oluşan bir ailedir. Şirket yalnızca onlar için çekirdekler ve araçlar (derleyiciler, hata ayıklama araçları vb.) geliştiriyor ve mimariyi üçüncü taraf üreticilere lisanslayarak para kazanıyor.

Bilmeyen varsa artık çoğu mobil cihaz ve tablet bu işlemci mimarisi üzerinde geliştiriliyor. Bu ailenin temel avantajı, çeşitli gömülü sistemlerde sıklıkla kullanılması nedeniyle düşük güç tüketimidir. Mimari zamanla gelişti ve ARMv7'den başlayarak 3 profil tanımlandı: 'A'(uygulama) - uygulamalar, 'R' (gerçek zamanlı) - gerçek zaman, 'M' (mikrodenetleyici) - mikrodenetleyici. Bu teknolojinin gelişim tarihini ve diğer ilginç verileri Wikipedia'da veya internette Google'da arayarak okuyabilirsiniz. ARM farklı çalışma modlarını destekler (Thumb ve ARM, ayrıca yakın zamanda ARM ve Thumb'ın bir karışımı olan Thumb-2 ortaya çıktı). Bu yazıda 32 bitlik bir komut setinin yürütüldüğü ARM modunun kendisine bakacağız.

Her ARM işlemcisi aşağıdaki bloklardan oluşturulur:

  • 37 kayıt (geliştirme sırasında yalnızca 17'si görünür)
  • Aritmetik mantık birimi (ALU) - aritmetik ve mantıksal görevleri gerçekleştirir
  • Namlu değiştirici - veri bloklarını belirli sayıda bit taşımak için tasarlanmış bir cihaz
  • CP15, ARM yardımcı işlemcilerini kontrol eden özel bir sistemdir
  • Talimat kod çözücü - talimatları bir dizi mikro işlem haline dönüştürmekle ilgilenir
Bunların hepsi ARM'in bileşenleri değil, ancak işlemci yapımı ormanına dalmak bu makalenin kapsamı dışındadır.
Boru hattı yürütme
ARM işlemcileri 3 aşamalı bir işlem hattı kullanır (ARM8'den başlayarak 5 aşamalı bir işlem hattı uygulandı). Örnek olarak ARM7TDMI işlemcisini kullanan basit bir boru hattına bakalım. Her talimatın yürütülmesi üç adımdan oluşur:

1. Numune alma aşaması (F)
Bu aşamada talimatlar RAM'den işlemci hattına akar.
2. Kod çözme aşaması (D)
Talimatların kodu çözülür ve türleri tanınır.
3. Yürütme aşaması (E)
Veri ALU'ya girer ve yürütülür ve elde edilen değer belirtilen kayıt defterine yazılır.

Ancak geliştirme sırasında, yükleme (LDR) veya saklama gibi çeşitli yürütme döngülerini kullanan talimatların olduğu dikkate alınmalıdır. Bu durumda yürütme aşaması (E) aşamalara (E1, E2, E3...) bölünür.

Koşullu yürütme
ARM derleyicisinin en önemli işlevlerinden biri koşullu yürütmedir. Her talimat koşullu olarak yürütülebilir ve bunun için son ekler kullanılır. Bir talimatın adına bir sonek eklenirse, onu çalıştırmadan önce parametreler kontrol edilir. Parametreler koşulu karşılamıyorsa talimat yürütülmez. Son ekler:
MI - negatif sayı
PL - pozitif veya sıfır
AL - talimatları her zaman uygula
Daha birçok koşullu yürütme eki vardır. Resmi belgelerdeki son eklerin ve örneklerin geri kalanını okuyun: ARM belgeleri
Artık düşünme zamanı...
Temel ARM birleştirici sözdizimi
Daha önce assembler ile çalışmış olanlar için aslında bu noktayı atlayabilirsiniz. Herkes için bu dille çalışmanın temellerini anlatacağım. Yani her montaj dili programı talimatlardan oluşur. Talimat şu şekilde oluşturulur:
(etiket) (talimat|işlenenler) (@ yorum)
Etiket isteğe bağlı bir parametredir. Talimat, işlemciye talimatların doğrudan anımsatıcısıdır. Temel talimatlar ve bunların kullanımı aşağıda tartışılacaktır. İşlenenler - sabitler, kayıt adresleri, RAM'deki adresler. Yorum, programın yürütülmesini etkilemeyen isteğe bağlı bir parametredir.
İsimleri kaydedin
Aşağıdaki kayıt adlarına izin verilir:
1.r0-r15

3.v1-v8 (değişken kayıtları, r4 ila r11)

4.sb ve SB (statik kayıt, r9)

5.sl ve SL (r10)

6.fp ve FP (r11)

7.ip ve IP (r12)

8.sp ve SP (r13)

9.lr ve LR (r14)

10.pc ve PC (program sayacı, r15).

Değişkenler ve sabitler
ARM assembler'da (pratik olarak) diğer programlama dilleri gibi değişkenler ve sabitler kullanılabilir. Aşağıdaki türlere ayrılırlar:
  • Sayısal
  • zeka oyunu
  • Sicim
Sayısal değişkenler şu şekilde başlatılır:
bir SETA 100; 100 değerinde bir sayısal değişken "a" oluşturulur.
Dize değişkenleri:
improb SETS "gerçek"; "literal" değerine sahip bir improb değişkeni yaratılır. DİKKAT! Değişken değeri 5120 karakteri aşamaz.
Boolean değişkenleri sırasıyla DOĞRU ve YANLIŞ değerlerini kullanır.
ARM montajcı talimatlarına örnekler
Bu tabloda daha fazla gelişme için gerekli olacak temel talimatları topladım (en temel aşamada :):

Temel talimatların kullanımını güçlendirmek için birkaç basit örnek yazalım, ancak önce bir kollu alet zincirine ihtiyacımız olacak. Linux üzerinde çalıştığım için şunu seçtim: frank.harvard.edu/~coldwell/toolchain (arm-unknown-linux-gnu toolchain). Linux'taki herhangi bir program kadar kolay bir şekilde kurulabilir. Benim durumumda (Rus Fedora) yalnızca web sitesinden rpm paketlerini yüklemem gerekiyordu.
Şimdi basit bir örnek yazmanın zamanı geldi. Program kesinlikle işe yaramaz olacak ama asıl önemli olan işe yarayacak :) İşte size sunduğum kod:
start: @ Programın başlangıcını gösteren isteğe bağlı satır mov r0, #3 @ r0 kaydını 3 mov r1, #2 değeriyle yükleyin @ Aynısını r1 kaydıyla yapın, yalnızca şimdi 2 değeriyle ekleyin r2, r1, r0 @ r0 ve r1 değerlerini toplayın, cevap r2'ye yazılır mul r3, r1, r0 @ r1 yazmacının değerini r0 yazmacının değeriyle çarpın, cevap r3'e yazılır stop: b stop @ Program sonlandırma satırı
.bin dosyasını elde etmek için programı derliyoruz:
/usr/arm/bin/arm-unknown-linux-gnu-as -o arm.o arm.s /usr/arm/bin/arm-unknown-linux-gnu-ld -Ttext=0x0 -o ​​arm. elf kolu .o /usr/arm/bin/arm-unknown-linux-gnu-objcopy -O ikili arm.elf arm.bin
(kod arm.s dosyasındadır ve benim durumumdaki araç zinciri /usr/arm/bin/ dizinindedir)
Her şey yolunda giderse, 3 dosyanız olacaktır: arm.s (gerçek kod), arm.o, arm.elf, arm.bin (gerçek yürütülebilir program). Programın çalışmasını kontrol etmek için kendi kol cihazınızın olmasına gerek yoktur. QEMU'yu kurmanız yeterlidir. Referans için:

QEMU, çeşitli platformların donanımlarını taklit etmek için ücretsiz ve açık kaynaklı bir programdır.

Intel x86 işlemcilerin ve G/Ç aygıtlarının emülasyonunu içerir. 80386, 80486, Pentium, Pentium Pro, AMD64 ve diğer x86 uyumlu işlemcileri taklit edebilir; PowerPC, ARM, MIPS, SPARC, SPARC64, m68k - yalnızca kısmen.

Syllable, FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android vb. üzerinde çalışır.

Yani arm'ı taklit etmek için qemu-system-arm'a ihtiyacınız olacak. Bu paket yum'da olduğundan Fedora'ya sahip olanlar için zahmet etmenize gerek yok ve sadece komutu çalıştırmanız yeterli:
yum qemu-sistem kolunu kurun

Daha sonra arm.bin programımızı yürütmesi için ARM emülatörünü başlatmamız gerekiyor. Bunu yapmak için QEMU için flash bellek olacak bir flash.bin dosyası oluşturacağız. Bunu yapmak çok kolaydır:
dd if=/dev/zero of=flash.bin bs=4096 count=4096 dd if=arm.bin of=flash.bin bs=4096 conv=notrunc
Şimdi QEMU'yu ortaya çıkan flash bellekle yüklüyoruz:
qemu-sistem kolu -M bağlantısı -pflash flash.bin -nographic -seri /dev/null
Çıktı şöyle bir şey olacak:

$ qemu-sistem kolu -M bağlantı -pflash flash.bin -nographic -seri /dev/null
QEMU 0.15.1 monitörü - daha fazla bilgi için "yardım" yazın
(qemu)

arm.bin programımız dört kaydın değerini değiştirmek zorunda kaldı, bu nedenle doğru işlemi kontrol etmek için aynı kayıtlara bakalım. Bu çok basit bir komutla yapılır: bilgi kayıtları
Çıkışta 15 ARM kaydının tümünü göreceksiniz ve bunlardan dördünün değerleri değişmiş olacak. Kontrol edin :) Kayıt değerleri, programın yürütülmesinden sonra beklenebilecek değerlerle eşleşiyor:
(qemu) bilgi kayıtları R00=00000003 R01=00000002 R02=00000005 R03=00000006 R04=00000000 R05=00000000 R06=00000000 R07=00000000 R08=00000000 R09=00 000000 R10=00000000 R11=00000000 R12=00000000 R13=00000000 R14= 00000000 R15=00000010 PSR=400001d3 -Z-- A svc32

Not: Bu yazımda ARM assembler'da programlamanın temellerini anlatmaya çalıştım. Umarım keyif almışsınızdır! Bu, bu dilin ormanına daha fazla dalmak ve ona programlar yazmak için yeterli olacaktır. Her şey yolunda giderse, kendim öğrendiklerim hakkında daha fazla yazacağım. Montajda yeni olduğum için hatalar varsa lütfen beni tekmelemeyin.

Herkese selam!
Mesleğim gereği Java programcısıyım. Son aylardaki çalışmalarım beni Android NDK için geliştirme ve buna bağlı olarak C'de yerel uygulamalar yazma konusunda bilgi sahibi olmaya zorladı. Burada Linux kitaplıklarını optimize etme sorunuyla karşı karşıya kaldım. Birçoğunun ARM için tamamen optimize edilmemiş olduğu ve işlemciyi ağır şekilde yüklediği ortaya çıktı. Daha önce neredeyse hiç montaj dilinde programlama yapmamıştım, bu yüzden ilk başta bu dili öğrenmeye başlamak zordu ama yine de denemeye karar verdim. Bu makale, tabiri caizse, yeni başlayanlar için yeni başlayanlardan yazılmıştır. Zaten öğrendiğim temel bilgileri anlatmaya çalışacağım, umarım bu birilerinin ilgisini çeker. Ayrıca profesyonellerden yapıcı eleştiriler almaktan memnuniyet duyacağım.

giriiş
Öncelikle ARM'ın ne olduğunu bulalım. Wikipedia şu tanımı veriyor:

ARM mimarisi (Gelişmiş RISC Makinesi, Acorn RISC Makinesi, gelişmiş RISC makinesi), ARM Limited tarafından geliştirilen lisanslı 32 bit ve 64 bit mikroişlemci çekirdeklerinden oluşan bir ailedir. Şirket yalnızca onlar için çekirdekler ve araçlar (derleyiciler, hata ayıklama araçları vb.) geliştiriyor ve mimariyi üçüncü taraf üreticilere lisanslayarak para kazanıyor.

Bilmeyen varsa artık çoğu mobil cihaz ve tablet bu işlemci mimarisi üzerinde geliştiriliyor. Bu ailenin temel avantajı, çeşitli gömülü sistemlerde sıklıkla kullanılması nedeniyle düşük güç tüketimidir. Mimari zamanla gelişti ve ARMv7'den başlayarak 3 profil tanımlandı: 'A'(uygulama) - uygulamalar, 'R' (gerçek zamanlı) - gerçek zaman, 'M' (mikrodenetleyici) - mikrodenetleyici. Bu teknolojinin gelişim tarihini ve diğer ilginç verileri Wikipedia'da veya internette Google'da arayarak okuyabilirsiniz. ARM farklı çalışma modlarını destekler (Thumb ve ARM, ayrıca yakın zamanda ARM ve Thumb'ın bir karışımı olan Thumb-2 ortaya çıktı). Bu yazıda 32 bitlik bir komut setinin yürütüldüğü ARM modunun kendisine bakacağız.

Her ARM işlemcisi aşağıdaki bloklardan oluşturulur:

  • 37 kayıt (geliştirme sırasında yalnızca 17'si görünür)
  • Aritmetik mantık birimi (ALU) - aritmetik ve mantıksal görevleri gerçekleştirir
  • Namlu değiştirici - veri bloklarını belirli sayıda bit taşımak için tasarlanmış bir cihaz
  • CP15, ARM yardımcı işlemcilerini kontrol eden özel bir sistemdir
  • Talimat kod çözücü - talimatları bir dizi mikro işlem haline dönüştürmekle ilgilenir
Bunların hepsi ARM'in bileşenleri değil, ancak işlemci yapımı ormanına dalmak bu makalenin kapsamı dışındadır.
Boru hattı yürütme
ARM işlemcileri 3 aşamalı bir işlem hattı kullanır (ARM8'den başlayarak 5 aşamalı bir işlem hattı uygulandı). Örnek olarak ARM7TDMI işlemcisini kullanan basit bir boru hattına bakalım. Her talimatın yürütülmesi üç adımdan oluşur:

1. Numune alma aşaması (F)
Bu aşamada talimatlar RAM'den işlemci hattına akar.
2. Kod çözme aşaması (D)
Talimatların kodu çözülür ve türleri tanınır.
3. Yürütme aşaması (E)
Veri ALU'ya girer ve yürütülür ve elde edilen değer belirtilen kayıt defterine yazılır.

Ancak geliştirme sırasında, yükleme (LDR) veya saklama gibi çeşitli yürütme döngülerini kullanan talimatların olduğu dikkate alınmalıdır. Bu durumda yürütme aşaması (E) aşamalara (E1, E2, E3...) bölünür.

Koşullu yürütme
ARM derleyicisinin en önemli işlevlerinden biri koşullu yürütmedir. Her talimat koşullu olarak yürütülebilir ve bunun için son ekler kullanılır. Bir talimatın adına bir sonek eklenirse, onu çalıştırmadan önce parametreler kontrol edilir. Parametreler koşulu karşılamıyorsa talimat yürütülmez. Son ekler:
MI - negatif sayı
PL - pozitif veya sıfır
AL - talimatları her zaman uygula
Daha birçok koşullu yürütme eki vardır. Resmi belgelerdeki son eklerin ve örneklerin geri kalanını okuyun: ARM belgeleri
Artık düşünme zamanı...
Temel ARM birleştirici sözdizimi
Daha önce assembler ile çalışmış olanlar için aslında bu noktayı atlayabilirsiniz. Herkes için bu dille çalışmanın temellerini anlatacağım. Yani her montaj dili programı talimatlardan oluşur. Talimat şu şekilde oluşturulur:
(etiket) (talimat|işlenenler) (@ yorum)
Etiket isteğe bağlı bir parametredir. Talimat, işlemciye talimatların doğrudan anımsatıcısıdır. Temel talimatlar ve bunların kullanımı aşağıda tartışılacaktır. İşlenenler - sabitler, kayıt adresleri, RAM'deki adresler. Yorum, programın yürütülmesini etkilemeyen isteğe bağlı bir parametredir.
İsimleri kaydedin
Aşağıdaki kayıt adlarına izin verilir:
1.r0-r15

3.v1-v8 (değişken kayıtları, r4 ila r11)

4.sb ve SB (statik kayıt, r9)

5.sl ve SL (r10)

6.fp ve FP (r11)

7.ip ve IP (r12)

8.sp ve SP (r13)

9.lr ve LR (r14)

10.pc ve PC (program sayacı, r15).

Değişkenler ve sabitler
ARM assembler'da (pratik olarak) diğer programlama dilleri gibi değişkenler ve sabitler kullanılabilir. Aşağıdaki türlere ayrılırlar:
  • Sayısal
  • zeka oyunu
  • Sicim
Sayısal değişkenler şu şekilde başlatılır:
bir SETA 100; 100 değerinde bir sayısal değişken "a" oluşturulur.
Dize değişkenleri:
improb SETS "gerçek"; "literal" değerine sahip bir improb değişkeni yaratılır. DİKKAT! Değişken değeri 5120 karakteri aşamaz.
Boolean değişkenleri sırasıyla DOĞRU ve YANLIŞ değerlerini kullanır.
ARM montajcı talimatlarına örnekler
Bu tabloda daha fazla gelişme için gerekli olacak temel talimatları topladım (en temel aşamada :):

Temel talimatların kullanımını güçlendirmek için birkaç basit örnek yazalım, ancak önce bir kollu alet zincirine ihtiyacımız olacak. Linux üzerinde çalıştığım için şunu seçtim: frank.harvard.edu/~coldwell/toolchain (arm-unknown-linux-gnu toolchain). Linux'taki herhangi bir program kadar kolay bir şekilde kurulabilir. Benim durumumda (Rus Fedora) yalnızca web sitesinden rpm paketlerini yüklemem gerekiyordu.
Şimdi basit bir örnek yazmanın zamanı geldi. Program kesinlikle işe yaramaz olacak ama asıl önemli olan işe yarayacak :) İşte size sunduğum kod:
start: @ Programın başlangıcını gösteren isteğe bağlı satır mov r0, #3 @ r0 kaydını 3 mov r1, #2 değeriyle yükleyin @ Aynısını r1 kaydıyla yapın, yalnızca şimdi 2 değeriyle ekleyin r2, r1, r0 @ r0 ve r1 değerlerini toplayın, cevap r2'ye yazılır mul r3, r1, r0 @ r1 yazmacının değerini r0 yazmacının değeriyle çarpın, cevap r3'e yazılır stop: b stop @ Program sonlandırma satırı
.bin dosyasını elde etmek için programı derliyoruz:
/usr/arm/bin/arm-unknown-linux-gnu-as -o arm.o arm.s /usr/arm/bin/arm-unknown-linux-gnu-ld -Ttext=0x0 -o ​​arm. elf kolu .o /usr/arm/bin/arm-unknown-linux-gnu-objcopy -O ikili arm.elf arm.bin
(kod arm.s dosyasındadır ve benim durumumdaki araç zinciri /usr/arm/bin/ dizinindedir)
Her şey yolunda giderse, 3 dosyanız olacaktır: arm.s (gerçek kod), arm.o, arm.elf, arm.bin (gerçek yürütülebilir program). Programın çalışmasını kontrol etmek için kendi kol cihazınızın olmasına gerek yoktur. QEMU'yu kurmanız yeterlidir. Referans için:

QEMU, çeşitli platformların donanımlarını taklit etmek için ücretsiz ve açık kaynaklı bir programdır.

Intel x86 işlemcilerin ve G/Ç aygıtlarının emülasyonunu içerir. 80386, 80486, Pentium, Pentium Pro, AMD64 ve diğer x86 uyumlu işlemcileri taklit edebilir; PowerPC, ARM, MIPS, SPARC, SPARC64, m68k - yalnızca kısmen.

Syllable, FreeBSD, FreeDOS, Linux, Windows 9x, Windows 2000, Mac OS X, QNX, Android vb. üzerinde çalışır.

Yani arm'ı taklit etmek için qemu-system-arm'a ihtiyacınız olacak. Bu paket yum'da olduğundan Fedora'ya sahip olanlar için zahmet etmenize gerek yok ve sadece komutu çalıştırmanız yeterli:
yum qemu-sistem kolunu kurun

Daha sonra arm.bin programımızı yürütmesi için ARM emülatörünü başlatmamız gerekiyor. Bunu yapmak için QEMU için flash bellek olacak bir flash.bin dosyası oluşturacağız. Bunu yapmak çok kolaydır:
dd if=/dev/zero of=flash.bin bs=4096 count=4096 dd if=arm.bin of=flash.bin bs=4096 conv=notrunc
Şimdi QEMU'yu ortaya çıkan flash bellekle yüklüyoruz:
qemu-sistem kolu -M bağlantısı -pflash flash.bin -nographic -seri /dev/null
Çıktı şöyle bir şey olacak:

$ qemu-sistem kolu -M bağlantı -pflash flash.bin -nographic -seri /dev/null
QEMU 0.15.1 monitörü - daha fazla bilgi için "yardım" yazın
(qemu)

arm.bin programımız dört kaydın değerini değiştirmek zorunda kaldı, bu nedenle doğru işlemi kontrol etmek için aynı kayıtlara bakalım. Bu çok basit bir komutla yapılır: bilgi kayıtları
Çıkışta 15 ARM kaydının tümünü göreceksiniz ve bunlardan dördünün değerleri değişmiş olacak. Kontrol edin :) Kayıt değerleri, programın yürütülmesinden sonra beklenebilecek değerlerle eşleşiyor:
(qemu) bilgi kayıtları R00=00000003 R01=00000002 R02=00000005 R03=00000006 R04=00000000 R05=00000000 R06=00000000 R07=00000000 R08=00000000 R09=00 000000 R10=00000000 R11=00000000 R12=00000000 R13=00000000 R14= 00000000 R15=00000010 PSR=400001d3 -Z-- A svc32

Not: Bu yazımda ARM assembler'da programlamanın temellerini anlatmaya çalıştım. Umarım keyif almışsınızdır! Bu, bu dilin ormanına daha fazla dalmak ve ona programlar yazmak için yeterli olacaktır. Her şey yolunda giderse, kendim öğrendiklerim hakkında daha fazla yazacağım. Montajda yeni olduğum için hatalar varsa lütfen beni tekmelemeyin.

1. Gerçek zamanlı saat sayacı etkinleştirilmelidir (1); Eğer saat ölçümü ana saat üreteci tarafından sağlanmıyorsa, saat kaynağı seçme biti temizlenir (2).

2. Kesme olayı seçim bitlerinden (3) biri veya her ikisi ayarlanmalıdır. Hangi olayların kesme isteğini tetikleyeceği seçilir (5).

3. Kesinti olay maskeleri (4, 7) belirtilmelidir.

2.5 ARM7'nin çeviricide programlanması hakkında

ARM7 komut seti (Bölüm 1.4) yalnızca 45 komut içerir; bunlar, adresleme yöntemlerinin, koşullu alanların ve değiştiricilerin çeşitliliği nedeniyle oldukça karmaşıktır. Montajcı programı hantaldır ve

İle okuması zor. Bu nedenle, ARM7 mimarisi için programlamada çevirici nadiren kullanılır.

Aynı zamanda üst düzey C dili birçok mimari özelliği programcıdan gizler. Programcı, çekirdek modunu seçme, yığın için bellek ayırma ve kesintileri yönetme gibi prosedürlere pratik olarak dokunmaz. Bu prosedürleri öğrenmek için en az bir basit programın montaj dilinde yazılmasında fayda vardır.

Ayrıca C kullanırken bile hala montaj diline başvurmanız gerekiyor.

1. Kontrol edilmeli C derleyicisi, optimizasyon sırasında önemli komutların gereksiz olduğunu düşünerek hariç tutulup tutulmadığını izler. Derleyici, yetersiz optimizasyon nedeniyle nispeten basit bir işlem için son derece verimsiz kod üretiyor mu? Derleyicinin, belirli bir algoritmanın verimliliğini artırmak için tasarlanmış donanım kaynaklarını gerçekten kullandığından emin olmak için.

2. Hataları veya istisnaların nedenlerini ararken (bölüm 2.4.1).

3. Performans veya bellek tüketimi açısından kesinlikle en uygun kodu elde etmek için (bölüm 2.2.20, 3.1.5).

Çeviricide program yazmanın temel tekniklerine bakalım

İle amaç, mikrodenetleyici tarafından yürütülen tüm kodu olduğu gibi ve aracısız olarak göstermektir C derleyicisi.

Çevirici tabanlı bir proje oluşturma prosedürü neredeyse C programlarıyla aynıdır (bölüm 2.3.1–2.3.3). Yalnızca iki istisna vardır:

a) kaynak metin dosyasına *.S uzantısı atanır;

b) burada STARTUP.S dosyasının programa bağlı olmadığı varsayılmaktadır.

2.5.1 Çeviricide program yazmak için temel kurallar

Bir montajcı programının metni genellikle dört sütun halinde biçimlendirilir. Her satırın dört alandan oluştuğunu söyleyebiliriz: etiketler, işlemler, işlenenler, yorumlar. Alanlar birbirlerinden sekme karakterleri veya boşluklarla ayrılır.

Ana alanlar işlemler ve işlenenlerdir. Geçerli işlemler ve sözdizimleri tablo (1.4.2)'de verilmiştir.

Etiket, komut adresinin sembolik bir gösterimidir. Her yerde etiket yerine, etiketin önündeki komutun adresi değiştirilecektir. Çoğu zaman etiketler kontrol aktarım komutlarında kullanılır. Her etiket benzersiz olmalı ve isteğe bağlıdır. Diğer birçok sürümün aksine, RealView derleyicisinde etiketler iki nokta üst üste (":") ile bitmez.

Yorumlar isteğe bağlı olarak satırın sonuna yerleştirilir ve noktalı virgül (“;”) ile ayrılır.

Basit bir örnek verelim.

2.5.2 Sözde komutlar

RealView derleyici sözde talimatları destekler. Sahte talimat, aslında işlemcinin talimat setine karşılık gelmeyen, ancak bir veya (nadiren) birkaç talimatın yerini aldığı anımsatıcı bir gösterimdir. Sözde komutlar bir tür makrodur ve sözdizimini basitleştirmeye yarar. Desteklenen sözde komutların listesi tabloda (2.5.1) verilmiştir.

2.5.3 Montaj direktifleri

Komutlardan farklı olarak yönergeler, mikro denetleyicinin belleğine yüklenen yürütülebilir kod oluşturmaz. Direktifler yalnızca montajcıya verilen talimatlardır; çalıştırılabilir kodun oluşumunu kontrol ederler.

Sık kullanılan RealView 4 assembler direktiflerine bakalım.

Ad EQU Sabiti

Sabitin eşanlamlısı haline gelen Sabite sembolik Ad adını atar. Temel amaç kontrol kayıtlarının adlarını tanıtmaktır.

ALAN Adı, Parametreler

Verilen Adla bir hafıza alanı tanımlar. Parametreleri kullanarak bellek alanının amacını belirlersiniz; örneğin VERİ (veri) veya KOD (kod). Tanımlanan alanın adresleri seçilen hedefe bağlıdır. KOD alanı 0x00000000 adresinden başlayarak, VERİ alanı ise 0x40000000 adresinden başlar. Programın RESET adında bir KOD alanına sahip olması gerekir. Program belleğine yerleştirilen sabitler, CODE, READONLY parametre çifti içeren bir bölümde bildirilmelidir.

Programa giriş noktasını belirtir, “başlangıcını” gösterir. Böyle bir direktifin programda her zaman mevcut olması gerekir. Genellikle AREA RESET, CODE direktifinden hemen sonra yerleştirilir.

Tablo 2.5.1 – RealView 4 derleyicisi tarafından desteklenen sözde talimatlar

Anımsatıcı gösterim

Operasyon

Gerçek uygulama

ve sözdizimi

ADR(Şart.)

kayıt defterine

PC ortak noktasından bir sabit ekleme veya çıkarma

ADD veya SUB komutları

ADRL(Koşul)

kayıt defterine

PC içeren çift ADD veya SUB

(genişletilmiş adres aralığı)

ASR(Koşul) (S)

Aritmetik sağa kaydırma

ASR(Koşul) (S)

kaydırma işleneni

LDR(İl.)

kayıt defterine

adresleme (PC + anında ofset)

Bir sabit yerleştirme

program belleğinde

LDR(indeks adresinden-

tion. PC ofset görevi görür.

LSL(Koşullu)(S)

Mantıksal sola kaydırma

LSL(Koşullu)(S)

kaydırma işleneni

LSR(Koşul) (S)

Mantıksal sağa kaydırma

LSR(Koşul) (S)

kaydırma işleneni

POP(Koşul)

Kayıtları yığından geri yükle

İyileşmek

kayıtlar

takım

LDMIA R13!,(...)

İTME(Koşul)

Koruma

kayıtlar

takım

STMDB R13!,(...)

ROR(Koşullu)(S)

Döngüsel kaydırma sağa

ROR(Koşullu)(S)

kaydırma işleneni

RRX(İlet.)(S)

Sağdan geçiş yap

1 haneli transfer

kaydırma işleneni

İsim SPACE Boyut

Belirli bir Boyuttaki verileri depolamak için hafıza ayırır. Ad, ayrılan alanın adresiyle eşanlamlı hale gelir. Adres alanının birliği bu direktifin hem kalıcı hem de RAM için kullanılmasına olanak tanır. Temel amaç RAM'de (DATA alanında) global değişkenler oluşturmaktır.

Etiket DCB/DCW/DCD Sabiti

Program belleğindeki “Flash” veriler (sayısal Sabitler). Etiket, verinin kaydedileceği adresle eş anlamlı hale gelir. Farklı direktifler (DCB, DCW ve DCD) farklı boyutlardaki verilere hizmet eder: bayt, 16 bit kelime, 32 bit kelime (sırasıyla).

Dosyanın sonunun bir işareti olarak hizmet eder. Bu yönergeden sonraki tüm metinler montajcı tarafından dikkate alınmaz.

2.5.4 Makrolar

Makro, bazı ortak işlemleri gerçekleştiren önceden tanımlanmış bir program parçasıdır. Kontrol aktarım komutları kullanılarak adlandırılan alt yordamların aksine, makroların kullanımı performansı düşürmez ancak programın bellek tüketimini azaltmaz. Çünkü bir makro her çağrıldığında, birleştirici metnin tamamını programa gömer.

Bir makro bildirmek için aşağıdaki yapıyı kullanın

$ Parametre1, $ Parametre2, ...

Parametreler, makro metnine her eriştiğinizde değiştirmenizi sağlar. Makronun içinde (gövdesinde) parametreler, önünde "$" işaretiyle birlikte kullanılır. Makro gövdesindeki parametreler yerine, çağrı sırasında belirtilen parametreler değiştirilir.

Makro şu şekilde çağrılır:

Ad Parametre1, Parametre2, ...

Durum kontrolü ve dallanmayı organize etmek mümkündür.

IF "$Parametre" == "Değer"

Lütfen bu tasarımın, mikrokontrolör tarafından durumun yazılımla kontrol edilmesine yol açmadığını unutmayın. Yürütülebilir kodun oluşturulması sırasında durum derleyici tarafından kontrol edilir.