assembly toplama işlemi / pic ile toplama işlemi yapılması...

Assembly Toplama Işlemi

assembly toplama işlemi

ASSEMBLY DİLİ

 

Assembly dili alt düzey bir programlama dilidir. Konuyla alakalı herhangi birşeyi anlamak için bilgisayar mimarisi hakkında bilgi edinmek gerekir. Basit bir bilgisayar modeli aşağıda verilmiştir.

 

Sistem Veriyolu(System Bus)  bilgisayarın çeşitli parçalarını birbirine bağlar.

CPU bilgisayarın kalbidir.Hesaplamaların çoğu CPU’nun içerisinde gerçekleşir.

RAM programların bilgisayarda yürütülmek için yüklendiği yerdir.

 

CPU’nun içi:

 

8086 CPU’nun 8 tane registeri vardır.

 

AX: biriktirici(accumulator) registerdir.(AH/AL olarak bölünmüştür)

BX: temel(base) registerdir.(BH/BL olarak bölünmüştür)

CX: sayaç(counter) registerdir.(CH/CL olarak bölünmüştür)

DX: veri(data) registeridir.(DH/DL olarak bölünmüştür)

SI: kaynak(source) indeks registeri

DI: gidilecek(destination) indeks registeri

BP: temel(base) işaretçisi

SP: yığıt(stack) işaretçisi

 

Registerların bu şekilde isimlendirilmesine rağmen, ne amaçla kullanılacağına programcı karar verir. Registerların esas görevi bir sayı(değişken) tutmaktır. Yukarıdaki registerlar 16 bit büyüklüğündedir.Örnek: 0011000000111001b(binary) or 12345 (decimal)

 

Genel amaçlı 4 register (AX, BX, CX, DX), iki farklı 8 bitlik registerlardan oluşmuştur.Eğer AX= 0011000000111001bise AH=00110000bve AL=00111001b olur. Aynı şey diğer 3 register içinde geçerlidir.

 

Bölüt(Segment) Registerları

 

CS: Geçerli programı çalıştıran bölüte işaret eder.

DS: Genellikle değişkenlerin tanımlandığı bölüte işaret eder.

ES: ekstra bölüt registeri, kullanım amacını programcı belirler.

SS: yığıtları içeren bölüte işaret eder.

 

Özel Amaçlı Registerlar

 

IP: komut işaretçisi

FP(Bayrak yazmacı) Mikroişlemcinin geçerli durumunu gösterir.

 

IP registerları CS bölüt registerıyla birlikte çalışır ve yürütülen komuta işaret eder.

 

Belleğe Erişim(Memory Access)

 

Belleğe erişim için 4 tane registerı kullanabiliriz: BX, SI, DI, BP

 

Bu registerları[ ]sembolü  içerisine koyarak değişik bellek yerlerine işaret edebiliriz.

 

[BX + SI]
[BX + DI]
[BP + SI]
[BP + DI]

[SI]
[DI]
d16 (variable offset only)
[BX]

[BX + SI + d8]
[BX + DI + d8]
[BP + SI + d8]
[BP + DI + d8]

[SI + d8]
[DI + d8]
[BP + d8]
[BX + d8]

[BX + SI + d16]
[BX + DI + d16]
[BP + SI + d16]
[BP + DI + d16]

[SI + d16]
[DI + d16]
[BP + d16]
[BX + d16]

 

MOV Komutu

 

  • İkinci işleneni(kaynak) birinci işlenene(gidilecek) kopyalar.
  • Kaynak işleneni dolaysız değer, genel amaçlı register veya bellek registerı olabilir.
  • Gidicelek işleneni genel amaçlı register veya bellek registerı olabilir.
  • İki işlenende aynı boyutta olmalıdır(byte yada word)

 

MOV REG, memory
MOV memory, REG
MOV REG, REG
MOV memory, immediate
MOV REG, immediate

 

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], variable, etc...

immediate: 5, -24, 3Fh, 10001101b, etc...             

 

 

Bölüt registerları için sadece bu şekildeki MOV komutları desteklenir

 

MOV SREG, memory
MOV memory, SREG
MOV REG, SREG
MOV SREG, REG

SREG: DS, ES, SS, and only as second operand: CS.

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], variable, etc...

                                                                

 

MOV komutu CS ve IP registerlarının değerini değiştirmek için kullanılamaz.

 

Aşağıdaki kısa program MOV komutunun kullanımını göstermektedir.

 

ORG 100h           ; this directive required for a simple 1 segment .com program. MOVAX, 0B800h     ; set AX to hexadecimal value of B800h. MOVDS, AX         ; copy value of AX to DS. MOVCL, 'A'        ; set CL to ASCII code of 'A', it is 41h. MOVCH, 1101_1111b ; set CH to binary value. MOVBX, 15Eh       ; set BX to 15Eh. MOV[BX], CX       ; copy contents of CX to memory at B800:015E RET                ; returns to operating system.  

        

 

Yukarıdaki kısa programı kod editorunde ‘; add your code here’ yazan yere kopyalayıp yapıştırın ve [Compile and Emulate] butonuna ya da klavyeden F5’e basın.

 

Emulator penceresi program yüklenmiş şekilde açılacak, daha sonra [Single Step]  butonuna basarak registerların değerini takip edebilirsiniz.

 

 

Yukarıdaki program direkt olarak video hafızasına yazar, burdan  MOV’un çok etkili bir komut olduğunu anlıyabilirsiniz.

 

Değişkenler

 

 Değişken bir bellek yeridir.Programcı için herhangi bir değeri 5A73:235B isimli bir adreste tutmaktansa , ‘var1’ isimli bir değişkende tutmak daha kolaydır, özellikle 10 veya daha fazla değişken varsa.

 

Bizim derleyicimiz iki türlü değişknei kabul etmektedir: BYTE yada WORD

Değişken bildirim sentaksı:

İsim   DB   değer

İsim   DW  değer

 

DB- Define Byte

DW-Define Word

 

İsim: Bir harfle başlaması gerekmesine rağmen, herhangi bir harf yada sayı kombinasyonu olabilir. İsimsiz bir değişkende tanımlanabilir, o zaman değişkenin bir adresi olur ama ismi olmaz.

 

Değer: Herhangi bir numaralandırma sistemi(hexadecimal, binary yada decimal) tarafından desteklenen bir sayısal değer olabilir yada  henüz başlangıç değeri atanmamış değişkenler için ‘?’ sembolüde olabilir.

 

Biraz öncede söyledğimiz gibi MOV komutu  değerleri kaynaktan gidilecek yere kopyalamak için kullanılır.MOV komutuyla ilgili başka bir örnek görelim:

 

ORG 100h MOV AL, var1MOV BX, var2 RET    ; stops the program. VAR1 DB 7var2 DW 1234h

 

Yukarıdaki kodu kaynak editörüne kopyalayın, derlemek için F5’e basın ve emulatore yükleyin. Aşağıdaki gibi bir netice almanız gerekir:

Derleyici Makine Kodunu ürettiği zaman, bütün değişken isimleri offsetleriyle yer değiştirir.

 

Bellek listesinde ilk sıra offseti, ikinci sıra hexadecimal değeri, üçüncü sıra decimal değeri ve son sırada ASCII karakter değerini ifade eder.

 

Derleyici karakter duyarlı değildir, ‘VAR1’ ve ‘var1’ aynı değişkeni ifade eder.

 

VAR1’in offset değeri 0108h , ve tam adresi 0B56:0108dir.

var2’nin offset değeri  0109h ve tam adresi 0B56:0109 dir. Bu değişken WORD’dur ve 2 bytelık yer tutar. Alttaki byte, alttaki adreste tutulur, dolayısıyla 34h 12h’dan önce yer alır.

 

Arrays(Dizilimler)

 

Arrayler, değişkenler zinciri olarak adlandırılabilir. Bir metin dizgisi, her bir karakterin bir ASCII karakter(0...255) ile ifade edildiği bir byte arrayidir.

 

Aşağıda bazı array tanımları bulunmaktadır.

 

a DB 48h, 65h, 6Ch, 6Ch, 6Fh, 00h
b DB 'Hello', 0

 

b a’nın tıpatıp kopyasıdır. Derleyici tırnak işareti içinde bir string gördüğü zaman, otomatik olarak onu bir bytelar kümesine dönüştürür. Aşağıdaki şekil, bu arrayler tanıtıldığı zamanki hafızanın bir bölümünü göstermektedir.

 

 

Arrayin herhangi bir elemanına köşeli ayraçlar vasıtasıyla ulaşabilirsiniz.

 

MOV AL, a[3]

 

Ayrıca herhangi bir dizin yazmacı(BX, SI, DI, BP) kullanabilirsiniz. Örneğin;

 

MOV SI, 3
MOV AL, a[SI]

 

Büyük bir array tanıtmak istiyorsanız DUP operatorünü de kullanabilirsiniz. DUP’un sentaksı

 

number DUP ( value(s) ) şeklindedir. Number kaç kopya istendiğini gösteren sayıdır, value kopyalanacak ifadedir.

 

Örneğin:

 

c DB 5 DUP(9) ifadesic DB 9, 9, 9, 9, 9 ifadesinin başka bir şeklidir.

Değeri 255’ten büyük yada -128’den küçük  sayıları tutmak için DB yerine DW de kullanılabilir.

 

 

Bir Değişkenin Adresini Alma

 

LEA(Load Effective Address) komutu ve alternatif OFFSET operatörü bulunmaktadır. OFFSET ve LEA komutlarının ikiside bir değişkenin offset (bağıl konum) adresini elde etmek için kullanılabilir.

 

Örnek

ORG 100h MOV    AL, VAR1              ;  VAR1’in değerini AL registerının içine atarak kontrol eder. LEA    BX, VAR1              ; VAR1 in adresini BX registerının içine alır. MOV    BYTE PTR [BX], 44h    ; VAR1’in içeriğini değiştirir. MOV    AL, VAR1              ; VAR1’in değerini AL registerının içine atarak kontrol eder. RET VAR1   DB  22h END
 Aşağıdaki örnekte LEA yerine OFFSET kullanılmıştır. 
ORG 100h MOV    AL, VAR1              ; VAR1’in değerini AL registerının içine atarak kontrol eder. MOV    BX, OFFSET VAR1       ; VAR1 in adresini BX registerının içine alır. MOV    BYTE PTR [BX], 44h    ; VAR1’in içeriğini değiştirir. MOV    AL, VAR1              ; VAR1’in değerini AL registerının içine atarak kontrol eder. RET VAR1   DB  22h END
  Constants(Sabitler) Sabitler, değişkenler gibidir, ancak sadece program derlenene kadar varlıklarını sürdürürler. Bir sabit tanımlandıktan sonra değeri değişmez. Sabitleri tanıtmak için EQU komutu kullanılır.  name EQU < any expression >  Örneğin:  ile  Kodları aynı işi yapmaktadır. Değişkenlere, programınız yürütülürken emulatorun “View” menüsünden “Variables” ı seçerek bakabilirsiniz.   Değişkenlere herhangi bir numaralandırma sistemindede bakılabilir. 
  • HEX - hexadecimal (base 16).
  • BIN - binary (base 2).
  • OCT - octal (base 8).
  • SIGNED - signed decimal (base 10).
  • UNSIGNED - unsigned decimal (base 10).
  • CHAR - ASCII char code (256 sembol vardır, bazı semboller gözle görülmez).

Programınız çalışırken değişkeninizin üzerine çift tıklayarak ve ya sağ tıklayıp edit diyerek yeniden düzenleyebilirsiniz.

 

Interrupts(İş Kesme İşareti)

Interruptlar, bir dizi fonksiyondan oluşur. Bu fonksiyonlar programı kolaylaştırır, bir karakter bastırmak için kod yazmaktansa, kısa yoldan interrupt’ı çagırabilirsiniz, o herşeyi yapar. Disk sürücüsüyle ve diğer donanımsal cihazlarla çalışan interrupt fonksiyonları da vardır. Bu çeşit interruptlara software interrupts(yazılımla iş kesme) denir.

 

Interruptlar değişik donanımlar tarafından da tetiklenebilir, bunlara hardware interrupts (donanımla iş kesme) denir. Biz şuan software interruptlarla ilgilenmekteyiz.

Interrupt(İş kesme işareti) göndermek için INT komutunu yazmak yeterlidir. Sentaksı:

INT value

Value 0’la 255 arası yada 0’la 0FF arası bir sayı olabilir. Genellikle hexadecimal sayılar kullanılır.

O zaman sadece 256 tane fonksiyon vardır, bu durum mantıklı değil diye düşünebilirsiniz. Her interruptın alt fonksiyonları olabilir. Alt fonksiyon tanımlamak için, AL registerı interrupt çağırmadan önce hazırlanmalıdır. Her bir interrupt 256 alt fonksiyona sahip olabilir. Dolayısıyla (256*256=65536) Genellikle AH registerı(yazmacı) kullanılır ama bazen diger registerlarda kullanılabilir.

Aşağıdaki örnek: INT 10H ve 0EH alt fonksiyonunu kullanarak ekrana “Hello!”mesajı bastırır. Bu fonksiyon imleci ilerleterek ve ekranı gerektiği kadar akıtarak ekranda karakter gösterir.

ORG    100h                    ;. Derleyiciye tek bölütlü .com dosyası oluşturması için talimat verir  ;Kullandığımız alt fonksiyon geri dönüşte; AH registerını değiştirmez, dolayısıyla AH’yi sadece ;bir kere hazırlanır.MOV    AH, 0Eh    ; alt fonksiyonu seç. ;INT 10h/0Eh alt fonksiyonu AL; registerının içindeki bastırılacak ;olan karakterin ASCII kodunu alır MOV    AL, 'H'    ; ASCII code: 72INT    10h        ;bastır MOV    AL, 'e'    ; ASCII code: 101INT    10h        ; bastır MOV    AL, 'l'    ; ASCII code: 108INT    10h        ; bastır MOV    AL, 'l'    ; ASCII code: 108INT    10h        ; bastır MOV    AL, 'o'    ; ASCII code: 111INT    10h        ; bastır MOV    AL, '!'    ; ASCII code: 33INT    10h        ; bastır RET               ; işletim sistemine dön

 Yukardaki kodu editorun kod bölümüne giderek kopyalayıp yapıştırın [Compile and Emulate] butonuna basarak çalıştırın.

 

Aritmetik ve Mantıksal Komutlar

Birçok aritmetik ve mantıksal komut işlemcinin durum yazmacını etkiler.

Gördüğünüz gibi bu yazmaçta 16 bit vardır, her bir bit bayrak(flag) olarak adlandırılır ve 0 yada 1 değeri alır.

  • Carry Flag (CF)(Elde Biti) - Bu bayrak(flag) işaretsiz taşma(unsigned overflow) olduğu zaman 1 değerini alır. Örneğin 255+1 şeklinde bir toplama yaptıgınız zaman(sonuç 0 la 255 arasında olmadıgı zaman). Overflow olmadığı zaman flag 0 değeri alır.
  • Zero Flag (ZF)(Sıfır Biti) - Sonuç sıfırsa 1, sonuç sıfır değilse 0 olarak ayarlanır.
  • Sign Flag (SF)(İşaret Biti) - Sonuç negatif olduğu zaman 1 olarak ayarlanır, sonuç positif olduğunda 0. Bu flag genellikle en önemli bitin değerini alır.
  • Overflow Flag (OF)(Taşma Biti) - Eğer işaretli taşma(signed overflow) varsa 1 olarak ayarlanır.Örneğin, 100+50 byteları topladığınız zaman(Sonuç -128..127 arasında değildir)
  • Parity Flag (PF)(Eşlik Biti) - Eğer sonuç içerisinde bir bitlikler çift sayı ise 1 olarak, eğer tek sayıysa 0 olarak ayarlanır.
  • Auxiliary Flag (AF)(Ek Bit) - Alt dörtlüde işaretsiz taşma(unsigned overflow) varsa 1 olarak ayarlanır.
  • Interrupt enable Flag (IF)(İş Kesme İşareti Etkin Biti) - Bu flag 1 olarak ayarlandığı zaman CPU interruptlara dış aygıtlardan reaksiyon verir.
  • Direction Flag (DF)(Yön Biti) - this flag is used by some instructions to process data chains, when this flag is set to 0 - the processing is done forward, when this flag is set to 1 the processing is done backward. Bu flag bazı komutlar tarafından veri zincirini işlemek için kullanılır. Bu flag 0 olarak ayarlandığı zaman işleme ileri doğru, 1 olarak ayarlandığı zaman geriye doğru yapılır.

3 tane komut grubu vardır.

Birinci grup:ADD, SUB,CMP, AND, TEST, OR, XOR

Şu çeşit işlenenler kabul edilir:

REG, memory
memory, REG
REG, REG
memory, immediate
REG, immediate

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], variable, etc...

immediate: 5, -24, 3Fh, 10001101b, etc...

İşlenenler arasında işlem bittiği zaman, sonuç hep ilk işlenende tutulur. CMP ve TEST komutları sadece flagları etkiler ve sonucu kaydetmezler.(Bu komutlar program çalıştığı esnada karar vermek için kullanılır)

Bu komutlar şu flagları etkiler:

CF, ZF, SF, OF, PF, AF.

  • ADD - İkinci işleneni birinci işlenene ekler.
  • SUB – İkinci işleneni birici işlenenden çıkarır.
  • CMP - Sadece flaglar için ikinci işleneni birinci işlenenden çıkarır.
  • AND - İki işlenenin bütün bitleri arasındaki mantıksal AND operatörüdür.

1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0

Gördüğünüz gibi sadece her iki tarafda 1 olduğu zaman 1 sonucunu elde ediyoruz.

  • TEST - AND ile aynıdır fakat bu operator sadece flaglar içindir.
  • OR - İki işlenenin bütün bitleri arasındaki mantıksal OR operatörüdür.

1 OR 1 = 1
1 OR 0 = 1
0 OR 1 = 1
0 OR 0 = 0

Gördüğünüz gibi en az bir bit 1 olduğu zaman 1 sonucunu elde ediyoruz.

  • XOR - İki işlenenin bütün bitleri arasındaki mantıksal XOR operatörüdür.

1 XOR 1 = 0
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0

Gördüğünüz gibi bitler birbirinden farklı olduğu zaman 1 sonucunu elde ediyoruz.

İkinci grup:MUL, IMUL, DIV, IDIV

Şu çeşit işlenenler kabul edilir:

       REG
       memory

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], değişkenler, etc...

MUL ve IMUL komutları sadece şu flagları etkiler:CF, OF


Eğer sonuç işlenenin boyutunun üzerindeyse bu flaglar 1, eğer aynıysa 0 olarak ayarlanır.

DIV ve IDIV komutları için flag tanımsızdır.

İşlenen byte olduğu zaman:
AX = AL * işlenen(operand).

İşlenen word olduğu zaman:
(DX AX) = AX * operand.

İşlenen byte olduğu zaman:
AX = AL * işlenen(operand).

İşlenen word olduğu zaman:
(DX AX) = AX * işlenen(operand).

İşkenen byte olduğu zaman:
AL = AX / işlenen(operand)
AH = kalan(remainder (modulus)) .

işlnenen word olduğu zaman:
AX = (DX AX) / işlenen(operand)
DX = kalan(remainder (modulus)) .

İşlenen  byte olduğu zaman:
AL = AX / işlenen(operand)
AH = kalan(remainder (modulus)).

İşlenen word olduğu zaman:
AX = (DX AX) / işlenen(operand)
DX = kalan(remainder (modulus))

 

Üçüncü grup:INC, DEC, NOT, NEG

Şu çeşit işlenenler kabul edilir:

    REG
    memory

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], değişkenler, etc...

INC, DEC komutları sadece şu flagları etkiler:
       ZF, SF, OF, PF, AF.

NOT komutu hiçbir flagı etkilemez

NEG komutu sadece şu flagları etkiler:
       CF, ZF, SF, OF, PF, AF.

  • NOT – İşlenenin her bir bitini tersine dönüştürür.
  • NEG – İşleneni negatif yapar (two's complement). İşlenenin her bir bitini tersine çevirir ve 1 ekler. Örneğin 5’i -5, -2’yi 2 yapar.

 

Yordamlar(Procedures)

Yordamlar, belirli bir görevi yapmak için programınızdan çağırabileceğiniz kod parçasıdır. Yordamlar programı daha yapısal ve kolay anlaşılır bir hale getirir. Genellikle programda çağırıldıkları yere  geri dönerler.

Yordam bildiriminin sentaksı:

name PROC

      ; burda program yordam kodunun olduğu yere gider

RET
name ENDP

name – yordamın adıdır,altta ve üstte aynı isim olmalıdır.Yordamların düzgün bir şekilde kapanıp kapanmadığını kontrol eder.

Muhtemelen, RET komutunun işletim sisteminden dönmek için kullanıldığını zaten biliyorsunuz.Aynı komut yordamdan dönmek için de kullanılır.(işletim sistemi programınızı özel bir yordam olarak görür)


PROC ve ENDP komutları, derleyici bildirimleridir, dolayısıyla hiçbir gerçek makina koduna çevrilmezler. Derleyici sadece yordamın adresini hatırlar.

CALL komutu yordamı çağırmak için kullanılır.

Örnek:

ORG    100h

 

CALL   m1

 

MOV    AX, 2

 

RET                   ; işletim sistemine döner.

 

m1     PROC

MOV    BX, 5

RET                   ; çağırana döner.

m1     ENDP

     END

Yukarıdaki örnek m1 yordamını çağırır, m1 yordamı MOV BX, 5 komutunu yürütür. Daha sonra program sonraki komutu yani MOV AX, 2 komutunu yürütür.

Parametleri yordamlara göndermek için çeşitli yollar vardır. Bunlardan en kolayı register kullanmaktır. Aşağıdaki örnek iki parametreyi AL ve BL registerlarına alır, bu parametreleri çarpar ve sonucu AX registerına yazar.

ORG    100h

 

MOV    AL, 1

MOV    BL, 2

 

CALL   m2

CALL   m2

CALL   m2

CALL   m2

RET                   ; işletim sistemine döner

 

m2     PROC

MUL    BL             ; AX = AL * BL.

RET                   ; çağıran yere döner.

M2     ENDP

END

Yukarıdaki örnekte, yordam her çağrıldığında AL registerı güncellenir, BL registerı değişmez. Bu algoritma 2’nin 4.kuvvetini alır. AX registerının içindeki sonuç 16(10h) olur.

Aşağıda yordam kullanarak ekrana Hello World! Mesajı yazan bir örnek yer almaktadır.

ORG    100h

 

LEA    SI, msg        ; Mesajın adresini SI’ya yükler

 

CALL   print_me

 

RET                   ; işletim sistemine döner

 

; ==========================================================

;Bu yordam bir string bastırır, bu string sıfır ile bitmelidir. Stringin adresi SI da tutulmalıdır.

print_me     PROC

 

next_char:

    CMP  b.[SI], 0    ; durmak için sıfır olup olmadığını kontrol eder.

    JE   stop         ;

 

    MOV  AL, [SI]     ; bir sonraki ASCII karakteri alır.

 

    MOV  AH, 0Eh      ; uzakyazıcı fonksiyon numarası

    INT  10h          ;  AL’de bir karakter bastırmak için iş kesme işaretçisi kullanma

 

    ADD  SI, 1        ; string diziliminin indexini ilerletir.

 

    JMP  next_char    ; geriye dön ve başka bir karakter yaz.

 

stop:

RET                   ; çağırana döner.

print_me     ENDP

; ==========================================================

 

msg    DB  'Hello World!', 0   ; sıfırla biten string

END

"b."- [SI]’dan önceki öntakı, wordleri değil byteları karşılaştırmamız gerektiği anlamına gelir. Wordleri karşılaştırmak istediğimiz zaman öntakı olarak "w." yazarız. Karşılaştırılan işlenenlerden biri register(yazmaç) ise, bunları yazmamıza gerek yok. Çünkü derleyici her bir registerın boyutunu bilir.

Makrolar(Macros)

Makrolar, yordamlara benzerler ama aslında öyle değildir. Yordamlar gibi görünürler ancak kodunuz derlenene kadar varlıklarını sürdürürler, derlemeden sonra bütün macrolar gerçek komutlarla yer değiştirir. Eğer bir makro tanımladıysanız ve kodunuzda kullanmadıysanız  derleyici onu görmezden gelir.

 

 

 

Makro tanımlaması:

 

name    MACRO  [parameters,...]

 

             <instructions>

 

ENDM

Yordamların tersine , makrolar onu kullanan kodun üstünde yer almalıdır. Örneğin:

MyMacro    MACRO  p1, p2, p3      MOV AX, p1     MOV BX, p2     MOV CX, p3 ENDM ORG 100h MyMacro 1, 2, 3 MyMacro 4, 5, DX RET

Yukarıdaki kod aşağıdaki gibi genişletilebilir.

MOV AX, 00001h
MOV BX, 00002h
MOV CX, 00003h
MOV AX, 00004h
MOV BX, 00005h
MOV CX, DX

Macrolar ve yordamlarla ilgili bazı önemli bilgiler:

  • Bir yordam çağırmak istediğiniz zaman CALL komutunu kullanmalısınız. Örneğin:

CALL MyProc

  • Bir makro çağırmak istediğiniz zaman , sadece  ismini yazmanız yeterlidir. Örneğin:

MyMacro

  • Yordamlar hafızada belli bir adreste bulunmaktadır, ve eğer bu yordamı 100 kere de kullansanız CPU kontrolü hafızanın bu bölgesine kaydıracaktır. RET komutuyla kontrol tekrar programa dönecektir. Yığıt(stack) dönüş adresini tutmak için kullanılır. CALL komutu 3 bytelık yer tutar, dolayısıyla çıktı dosyasının boyutu önemsiz bir oranda artar,o yüzden  yordamın kaç kere çağırıldığının önemi yoktur.
  • Makro doğrudan programın içinde genişletilir. Bu yüzden eğer makroyu 100 kere kullanmak isterseniz, derleyici makroyu 100 kere genişletecektir, yürütülebilir çıktı dosyası büyüyecektir , ve her seferinde makronun bütün komutları içerilecektir.
  • Yordamlara parametre göndermek için yığıtlar yada genel amaçlı registerlar kullanılabilir.
  • Makroya parametre göndermek için, göndermek istediğiniz parametreleri makronun adından sonra yazmanız yeterlidir.

MyMacro 1, 2, 3

  • Makronun bitişini belirtmek için ENDM bildirimi yeterlidir.

 

  • Yordamın bitişini belirtmek için, ENDP bildiriminden önce yordamın adını yazmanız gerekir.

 

Makrolar doğrudan kodun içinde genişletilir, bu nedenle eğer kodun içinde etiketler(labeller varsa) , makroyu birden fazla kullandığınız takdirde "Duplicate declaration" hata mesajını alırsınız. Bu tür problemleri engellemek için, değişkenler, etiketler ve yordamlar tarafından takip edilen  LOCAL bildirimler kullanınız.

MyMacro2    MACRO

                    LOCAL label1, label2

 

                    CMP  AX, 2

                    JE label1

                    CMP  AX, 3

                    JE label2

                    label1:

                                          INC  AX

                    label2:

                                          ADD  AX, 2

ENDM

 

 

ORG 100h

 

MyMacro2

 

MyMacro2

 

RET

Eğer makroları çeşitli programlarda kullanmayı planlıyorsanız, bütün makroları ayrı bir dosyada tutmak iyi bir fikir olabilir. Bu dosyayı Inc klasörünün içine koyun ve INCLUDE dosya_adı bildirimiyle makroları kullanın. Böyle bir dosya örneği için Library of common functions - emu8086.inclinline tıklayın.

  

Popüler Yazılar & Sayfalar

Hafızada(memory) iki adet sayı olsun. hekzadesimal 6553h sayısı  0x00B00 adresinde, hekzadesimal 1287h sayısı 0x00B02 adresinde bulunuyor olsun. Bu iki sayının toplamını,farkını,çarpımını,bölümünü 0x00B10 adresinden başlayarak belleğe sırası ile yazalım.

—————————

org 1000

;Not: kodlar intel syntaxına uygun olarak yazılmıştır.

;sayıları bellek alanlarından yazmaçlara (register) kopyalayalım.

MOV ax, [0x00B00]                ; 6553h sayısını ax yazmacına kopyaladık.

MOV bx, [0x00B02]; 1287h sayısını bx yazmacına kopyaladık.

;TOPLAMA

ADD ax,bx; bu komutla iki sayı toplandı ve ax yazmacına yerleştirildi.

MOV [0x00B10], ax               ;  toplamı ax yazmacından belirtilen bellek adresine kopyaladık.

MOV ax, [0x00B00]; 6553h sayısını ax yazmacına tekrar kopyaladık , çünkü biraz önce toplam yazılmıştı. (bx’teki sayı ;değişmedi)

;ÇIKARMA

SUB ax, bx                            ;  bu komutla 6553h sayısından 1287h sayısı çıkarıldı ve ax yazmacına kopyalandı.

MOV [0x00B12], ax              ; farkı ax yazmacından belirtilen bellek adresine kopyaladık.

;ÇARPMA

;Çarpma komutu olan MUL tek operand alır. Diğer operand MUL komutunun aldığı operandın (bit olarak) boyutuna göre ah ;ya da ax ten otomatik olarak alınır (konumuz olmayan sonraki işlemcilerde eax ten de alınabilir.).

;İşlem sonucu eğer 8 bit ise ax yazmacına, 16 bit ise yüksek anlamlı kısmı dx ‘e düşük anlamlı kısmı ax ‘e olmak üzere dx:ax ‘e kaydedilir.

MOV ax, [0x00B00]       ; 6553h sayısını ax yazmacına tekrar kopyaladık , çünkü biraz önce fark yazılmıştı.

;bx yazmacında halen 1287h sayısı var ancak örneğin açıklığı açısından yeniden kopyalayalım.

MOV bx, [0x00B02]      ; 1287h sayısını bx yazmacına kopyaladık.

;MUL komutu aldığı operandın 16 bit veya 8 bit oluşuna göre değişik davranış gösterir

MUL bx                         ; bu komut bx’ teki sayı ile ax’ ten aldığı sayıyı çarptı ve dx:ax’ e yazdı. bx 16 bit olduğu için ax’ in ;doğrudan alındığına dikkat edin.Eğer bx yerine bl (veya 8 bitlik başka birşey) yazsaydık sonuç sadece ax’e kaydedilecekti.

;burada kullandığımız MUL işaretsiz çarpma yapar. İşaretli için IMUL kullanılmalıdır.

;sonuç olan 32 bitlik 075544C5h sayısı dx:ax ‘e kaydedildi.

MOV [0x00B14] , dx      ; sonucun 16 bitini belirtilen bellek adresine kopyaladık.

MOV [0x00B16] , ax ; sonucun diğer 16 bitini belirtilen bellek adresine kopyaladık.

;BÖLME

; Bölme komutu olan DIV tek operand alır, bu bölendir. Diğer operand 8 bitlik bölmede ax’ten 16 bitlik bölmede dx:ax’ ten

;otomatik olarak alınır. Yani bölünenin uzunluğunu DIV komutunun aldığı operand olan bölen belirler.

; 8 bitlik bölmede al bölüm, ah kalan ;16 bitlik bölmede ax bölüm dx kalanı tutar.

MOV ax, [0x00B00]    ; 6553h sayısını ax yazmacına tekrar kopyaladık.

MOV bx, [0x00B02]    ; 1287h sayısını bx yazmacına kopyaladık (bx te zaten bu değer vardı, örneğin açıklığı açısından yeniden ;kopyaladık)

;BÖLME

;DIV komutu aldığı operandın 16 bit veya 8 bit oluşuna göre değişik davranış gösterir.

DIV bx                        ; bx yazmacındaki değer bölen olarak alındı ve ax’ teki  değeri böldü. Bölüm (05h) ax’ e  , kalan ;(08b0h) dx’ e kaydedildi. Eğer bx yerine 8 bit bir operand verseydik bu sefer bölüm al’ye kalan ah’a kaydedilecekti.

;burada kullandığımız DIV işaretsiz bölme yapar. İşaretli için IDIV kullanılmalıdır.

MOV [0x00B18] , ax; sonucu belirtilen bellek adresine kopyaladık.

hlt                                ;programı sonlandırdık

——————

Bunu beğen:

BeğenYükleniyor...

Bu yazı Programlama, Uncategorized içinde yayınlandı ve 8086, add, assembly, ax, çarpma, bölme, bx, division, dizi, mov, mul, multiplication, toplama olarak etiketlendi. Kalıcı bağlantıyı yer imlerinize ekleyin.

yollar

Bir mikroişlemcide 3 adet yol vardır ;

  1. Adres Yolu : Adres/Veri seçilir.
  2. Kontrol Yolu : Okuma işlemimi yoksa yazma işlemimi yapılacağı belirlenir.
  3. Veri Yolu : Veri gönderilir.

CPU tarafından gerçekleştirilen iki temel işlem vardır. Birincisi komutların yorumlanarak doğru bir sırada gerçekleşmesini sağlayan kontrol işlevi; diğeri toplama, çıkarma vb. özel matematik ve mantık işlemlerinin gerçekleştirilmesini sağlayan icra işlevidir. Bir mikroişlemcinin özelliklerini belirleyen bazı faktörler vardır. Bunlar;

  • Kelime Uzunluğu : İşlemcinin bir defada işleyebileceği verinin büyüklüğü.
  • Komut İşleme Hızı : Frekans ve zaman ters orantılıdır. İşlemcinin frekesı ne kadar yüksekse, komut işleme hızı düşer. Yani bu komutların daha kısa sürede işlenmesi anlamına gelir. ( F.T=1 )
  • Adres Büyüklüğü : Bellekler mikroişlemci tarafından adres yoluyla adreslenirler. Adres yolunun sayısı ne kadar fazla olursa adresleme kapasitesi de ona göre büyük olur.
  • Kaydedici Sayısı Ve Yapısı
  • Değişik Tipteki Komutlar : Bİr mikroişlemcide komut sayısının çok olması sisteme kolaylık sağlar ama bizim için önemli olan aynı zamanda bu komutların az cycle (devir, dolaşım, dönme) ile çalışmasıdır.
  • Farklı Adresleme Metotları : Bir verinin nasıl ve ne şekilde yerleştireleceği veya bellekten nasıl ve hangi yöntemle çağrılacağının belirlenmesi (doğrudan, dolaylı, indisli adresleme gibi) programcıya ekstra kolaylık sağlar.
  • İlave Edilecek Devrelerle Uyum : Mikroişlemciler bir sistemde tek başına kullanılamaz. EPROM, RAM, ROM vb. elemanlara ihtiyaç duyarlar ve bu elemanlar kullanılırken de mikroişlemciyle uyumlu olup olmaması önemlidir.

Mikroişlemciler farklı yapılarda olmasına rağmen temelde şu birimleri içerir :

  • Akümülatör
  • Program Sayıcı ( Program Counter – CP )
  • Komut Saklayıcı ( Instruction Register – IR )
  • Komut Kod Çözücüsü
  • Durum Saklayıcısı ( Condition Code Register – CCR )
  • Aritmatik Mantık Birimi ( Aritmatic Logic Unit – ALU )
  • Kontrol Birimi
  • Yığın Göstergesi ( Stack Point – SP )

Bunların bir kısmını açıklamak gerekirse;

Akümülatör : MİB (Merkezi İşlem Birimi)’ nin ana saklayıcısıdır ve veri yolu ile aynı bit uzunluğuna sahiptir. ALU’nun en önemli ve temel kaydedicisidir. ALU’da işlenecek veriler önce bu kaydediciye alınır ve işlendikten sonra sonuç burada bulunur. Dört işlem operasyonlarında kullanılır. Akümülatördeki bilgi hafızaya alındıktan sonra bilgi silinmez. Bilgi hem akümülatörde hem de bellekte bulunur.

Program Sayıcı : Bir programı oluşturan komutlar ve veriler normalde bellekte saklanır. Bilgisayarın çalışması sırasında hangi verinin hangi sırayla kullanılacağının bilinmesi gerekir. İşte bu görevi program sayıcı denen register yerine getirir. Program sayıcı, herhangi bir programın çalışması sırasında bir sonra işlenecek olan komutun bulunduğu adresi içerisinde barındırır.

Komut Kaydedicisi : Komut kodlarının geçici olarak tutulduğu yerdir.

Durum Saklayıcısı :CCR - Condition Code RegisterDurum bayrakları adı verilen bu kaydedici 8 bitliktir ve MİB’in en önemli kaydedicilerindendir. Durum kaydedicisindeki veriler istendiğinde MİB’in  durumunu programa belirtmek için kullanılır. Aritmatik ve mantık biriminde işlenen komutların sonuçları bu bayraklara etki eder ve işlem bu sonuçlara göre yönlenir.

-Elde Bayrağı : 8 bitlik 2 sayının toplanması veya çıkarılması gibi aritmatik işlemlerin sonucunda 8. bitten 9. bite taşma varsa bu bayrak 1 olur.
-Eşlik/Taşma Bayrağı : Bu bayrak, işaretli (signed) iki sayının birbirinen çıkarılması veya toplanması sonucu durumunu değiştirir. Taşma, 8 bit aritmatik işlemin sonucunda elde edilen değerin -128 den az yada +127’den fazla olması durumunda ortaya çıkar. Bu durumda taşma bayrağı 1, aksi durumda 0’dır.
-Sıfır Bayrağı : Herhangi bir veri transferi yada işlenmesi sonucunda, sonucun sıfır çıkması durumunda aktif olarak 1 olur, aksi durumda 0’dır.
-İşaret Bayrağı : Bu bayrak sayının + veya – olduğubu gösterir 7inci bit 0 ise veri pozitif(+), 1 ise negatif(-) sayıdır.

Aritmatik Ve Mantık Birimi ( Aritmatic And Logic Unit) : ALU’nun yaptığı işlemleri toplama, çıkarma, çarpma, bölme, karşılaştırma, artırma, azaltma, tümleme, sağdan sola kaydırma, döndürme işlemleri olmak üzere aritmatiksel işlemler ve and, or ,exor, not olamk üzere mantıksal işlemler olarak 2 gruba ayırmak mümkündür. ALU işlemleri ADDER ve SHIFTER adı verilen iki asıl devre ve akümülatör, geçici kaydedici ve durum kaydedici adı verilen yardımcı ünitelerle gerçekleştirir.

Kontrol Birimi : Bu kısım sistemin tüm işleyişinden ve işlemin zamanında yapılmasından sorumludur.

Yığın Göstergesi (SP) : RAM’in herhangi bir yerinde olabilen yığının en üst gözünün 16 bitlik adresidir. Belleğin yığın olan bu bölümü ‘son giren ilk çıkar’ (first-in first-out) (LIFO) prensibine göre çalışır. Sourcetimesta verilen basit bir örnek ile “Uçaktan otobüse binip terminal binasına gitmeniz gibidir, otobüs’e son binen kapıya yakın olur, kapıdan ilk çıktığı için de pasaport kuyruğunda eziyet çekmez. Aynı koşul uçağa binerken de geçerlidir, uçağa son yüklenen bagaj ilk çıkar.”

Yazar : Uğur ESKİCİ

Kaynak göstermek koşulu ile alıntı yapabilirsiniz. Assembly öğreniyorum yazı dizim, 6802 Intel işlemcileri baz alınarak kendi yorumlarım/anlatımlarım, ders notlarım ve çeşitli internet kaynaklarından ufak alıntılar ile düzenlenlenerek yazılmıştır.

nest...

oksabron ne için kullanılır patates yardımı başvurusu adana yüzme ihtisas spor kulübü izmit doğantepe satılık arsa bir örümceğin kaç bacağı vardır