Programming 8086 – Kısım II Program Akışı ve Döngüler Mikroişlemciler Programming 8086 – Kısım II Program Akışı ve Döngüler
İçerik Program Akış Kontrolü Koşullu komutlar Döngüler
Program Akış Kontrolü Program akışını kontrol etmek çok önemlidir. Bu kısım, programın, oluşabilecek farklı durumlara göre karar verebilmesini sağlar. C programlama dilindeki if durumunu hatırlayınız. Assembly dilinde, akış kontrolü, Jump komutları ile sağlanır.
Şartsız Atlamalar (Jump) Programda, kontrolü başka bir satıra atlatan temel komut JMP komutudur: JMP etiket Programınızda etiket tanımlamak için, adını yazın ve ":" ekleyin. Bir etiket, herhangi bir karakter kombinasyonu olabilir. Ancak bir rakam ile başlayamaz. Örnekler: etiket1: etiket2: a:
Etiketler hakkında Etiketler, komut ile aynı satırda olabileceği gibi, ayrı bir satırda da olabilir. Örnekler: x1: MOV AX, 1 x2: MOV AX, 2
JMP Örneği ORG 100H MOV AX, 5 ; AX’e 5 yaz. MOV BX, 2 ; BX’e 2 yaz. JMP calc ; 'calc‘e git. back: JMP stop ; 'stop‘a git. calc: ADD AX, BX ; AX’e BX ilave et. JMP back ; 'back‘e git. stop: RET ; işletim sistemine dön.
JMP detayları Üç farklı JMP komutu çeşidi bulunur: Short Jump – kısa atlama Near Jump – yakın atlama Far Jump – uzak atlama Short ve near atlamalar segment içi atlamalardır. far atlamalar ise segmentler arası atlamalardır.
Jump Tipleri
Short Jump – Kısa atlama Jump adresi, opcode’da kaydedilmez. Opcode’dan hemen sonra bir atlama mesafesi belirtilir. Short jump’lara göreceli jump’lar da denilir. Atlama mesafesi, -128 ile +127 aralığındadır.
Short Jump Gösterimi Atlama mesafesi, IP (Instruction Pointer)a ilave edilir. Bu sayede, mevcut code segment’inde bir jump adresi oluşturulur. Bir sonraki komutta, oluşturulan bu yeni adrese gidilir.
Short Jump Örneği 0000 33 DB XOR BX, BX 0002 BB 0001 BASLA: MOV AX, 1 0005 03 C3 ADD AX, BX 0007 EB 17 JMP SHORT SONRAKI ... 0020 8B D8 SONRAKI: MOV BX, AX 0022 EB DE JMP BASLA Not: SHORT ekini kullanmanıza da gerek yoktur. Çünkü, compiler, hangi jump komutunun uygun olduğunu seçer.
Near Jump – Yakın atlama Yakın atlama da kısa atlamaya benzer. Tek fark, atlama mesafesinin daha uzun olmasıdır. Yakın atlamada, mevcut code segment’inde ±32K bayt lık bir mesafeye atlama yapılabilir. Yakın atlama da göreceli bir atlamadır.
Near Jump Örneği 0000 33 DB XOR BX, BX 0002 BB 0001 BASLA: MOV AX, 1 0005 03 C3 ADD AX, BX 0007 E9 F601 JMP SONRAKI ... 0200 8B D8 SONRAKI: MOV BX, AX 0202 E9 FDFD JMP BASLA Not: Atlama mesafesi olarak F601 belirtilmiştir. Gerçek atlama mesafesi ise 01F6’dır. Unutmayın, yüksek bayt, ikinci bayt’a yazılır (little endian).
Far Jump – Uzak atlama Uzak atlama komutunda, atlamanın yapılacağı yeni bir segment ve offset adresi alınır. Uzak atlama komutu bazen FAR PTR ile gösterilir. Uzak atlamayı elde etmenin bir başka yolu da etiketi, uzak etiket olarak tanımlamaktır. Bir etiketin uzak olarak işaretlenmesi için, mevcut code segment’inde veya prosedüründe yer almaması gereklidir. Compiler, uzak etiket tanımlamasını otomatik olarak yapar.
Şartlı atlamalar JMP komutunda olduğu gibi koşulsuz bir atlama yapılmaz. Bu komutlarda, belli bir durum olduğunda atlama yapılır. Şartlı atlamalar, her zaman kısa atlamalardır. Bu komutlar, üç gruba ayrılabilir: Birinci grup, tek bir bayrağı kontrol eder. İkinci grup, sayıları yönlü olarak kontrol eder. Üçüncü grup, sayıları yönsüz olarak kontrol eder.
Genel Yapı Şartlı atlama komutlarının genel yapısı şu şekildedir: <Şartlı atlama komutu> <etiket> Örnek: JC etiket1 Eğer test edilen durum gerçekleşmiş ise, etiket’e atlama yapılır. Eğer test edilen durum gerçekleşmemiş ise, bir sonraki komut çalıştırılır.
Tek bir bayrağı kontrol eden atlama komutları Tanımlama Durum Karşıtı JZ, JE Sıfır (eşit) - Jump if Zero (Equal) Z = 1 JNZ, JNE JC, JB, JNAE Carry (küçük; eşitten büyük değil) - Jump if Carry (Below, Not Above Equal) C = 1 JNC, JNB, JAE JS Yönlü - Jump if Sign S = 1 JNS JO Overflow - Jump if Overflow O = 1 JNO JPE, JP Çift parity - Jump if Parity Even P = 1 JPO, JNP Jump if Not Zero (Not Equal) (sıfır değil ise) Z = 0 Jump if Not Carry (küçük değil; eşitten büyük - Not Below, Above Equal) C = 0 Yönlü değil - Jump if Not Sign S = 0 Overflow değil - Jump if Not Overflow O = 0 Tek parity - Jump if Parity Odd (No Parity) P = 0
Yönlü sayılar için atlama komutları Instruction Description Condition Opposite JE, JZ Eşit is e - Jump if Equal (=) Sıfır ise - Jump if Zero Z = 1 JNE, JNZ Eşit değil ise - Jump if Not Equal (≠) Sıfır değil ise - Jump if Not Zero Z = 0 JG, JNLE Büyük ise - Jump if Greater (>) Küçük veya eşit değil ise - Jump if Not Less or Equal (not <=) and S = O JNG, JLE JL, JNGE Küçük ise - Jump if Less (<) Büyük veya eşit değil ise - Jump if Not Greater or Equal S ≠ O JNL, JGE JGE, JNL Büyük veya eşit ise - Jump if Greater or Equal (>=) Küçük değil ise - Jump if Not Less JNGE, JL JLE, JNG Küçük veya eşit ise - Jump if Less or Equal (<=) Büyük değil ise - Jump if Not Greater or JNLE, JG
Yönsüz sayılar için atlama komutları Instruction Description Condition Opposite JE, JZ Eşit ise - Jump if Equal (=) Sıfır ise - Jump if Zero Z = 1 JNE, JNZ Eşit değil ise - Jump if Not Equal (≠) Sıfır değil ise - Jump if Not Zero Z = 0 JA, JNBE Büyük ise - Jump if Above (>) Küçük veya eşit değil ise - Jump if Not Below or Equal C = 0 and Z = O JNA, JBE JBE, JNA Küçük veya eşit ise - Jump if Below or Equal (<=) Büyük değil ise - Jump if Not Above C = 1 or JNBE, JA JB, JNAE, JC Küçük ise - Jump if Below (<) Büyük veya eşit değil ise - Jump if Not Above or Equal Carry ise - Jump if Carry JNB, JAE, JNC JAE, JNB, JNC Büyük veya eşit ise - Jump if Above or Equal (>=) Küçük değil ise - Jump if Not Below Carry değil ise - Jump if Not Carry
Öğrnek jnc a jnb a jae a mov ax, 4 a: mov ax, 5 ret
Yönlü veya yönsüz? Bir karşılaştırmadaki sayılar, yönlü veya yönsüz olabilir. Yönlü sayılar karşılaştırıldığında, “greater then” ve “less then” gibi terimlerini içeren komutları kullanın. Yönsüz sayılar karşılaştırıldığında ise, “above” ve “below” gibi terimleri içeren komutları kullanın.
Koşullu atlama örneği ORG 100H MOV AL, 25 ; AL’ye 25 değerini ata. MOV BL, 10 ; BL’ye 10 değerini ata. CMP AL, BL ; compare (karşılaştır) AL - BL. JE equal ; AL = BL (Z = 1) ise atla. MOV CX, 1 ; Eğer buraya gelmiş ise AL<>BL JMP stop ; CX’i set et, ve stop’a atla. equal: ; Eğer buraya gelmiş ise, MOV CX, 0 ; AL = BL’dir, CX’i temizle. stop: RET ; Her durumda buraya gel.
Döngüler Komut Operasyon ve atlama koşulu Karşıtı LOOP Decrease CX, jump to label if CX not zero DEC CX and JCXZ LOOPE Decrease CX, jump to label if CX not zero and equal (Z = 1) LOOPNE Decrease CX, jump to label if CX not zero and not equal (Z = 0) LOOPNZ Decrease CX, jump to label if CX not zero and Z = 0 LOOPZ Decrease CX, jump to label if CX not zero and Z = 1 JCXZ Jump to label if CX is zero OR CX, CX and JNZ
Döngü örneği : C Kodu İki array’in içeriklerini toplayan ve sonucu başka bir array’de saklayan bir program yazınız. short arr1[100]; short arr2[100]; int count = 100; int ndx = 0; while (count > 0) { arr2[ndx] = arr1[ndx] + arr2[ndx]; ndx++; count--; }
Döngü örneği: Assembly Kodu org 100h mov cx, 100 ; Bloklardaki eleman sayısı mov bx, 0 ; index’i başlat L1: mov ax, BLOCK1[bx];BLOCK1’deki sıradaki sayıyı al Add ax,BLOCK2[bx];BLOCK2’deki sıradaki sayıyı ekle mov BLOCK2[bx], ax ; sonucu sakla add bx, 2 ; Bir sonraki elemana geç loop L1 Ret BLOCK1 DW 100 DUP (1) BLOCK2 DW 100 DUP (2)
Başka bir çözüm org 100h mov cx, 100 ; Bloklardaki eleman sayısı mov SI, offset BLOCK1 mov DI, offset BLOCK2 L1: mov ax, [SI] ; BLOCK1’deki sıradaki sayıyı oku add ax, [DI] ; BLOCK2’deki sıradaki sayıyı ekle mov [DI], ax ; Sonucu sakla add SI, 2 ; Bir sonraki elemana geç add DI, 2 loop L1 Ret BLOCK1 DW 100 DUP (1) BLOCK2 DW 100 DUP (2)
Başka bir çözüm daha ORG 100h MOV CX, 100 ; bloklardaki eleman sayısı MOV SI, offset BLOCK1 MOV DI, offset BLOCK2 L1: LODSW ; Kaynağı AX’e oku ADD AX, [DI] ; BLOCK2’deki sıradaki sayıyı ekle STOSW ; sonucu hedefte sakla. LOOP L1 RET BLOCK1 DW 100 DUP (1) BLOCK2 DW 100 DUP (2)
Öğrnek 3 org 100h jmp start vec1 db 1, 2, 5, 6 vec2 db 3, 5, 6, 1 vec3 db ?, ?, ?, ? start: lea si, vec1 lea bx, vec2 lea di, vec3 mov cx, 4 sum: mov al, [si] add al, [bx] mov [di], al inc si inc bx inc di loop sum ret
İçiçe Döngüler Döngüler, temel olarak atlamalar gibidirler. Döngüleri, döngü komutlarını kullanmadan, sadece atlama komutlarını kullanarak da yapmak mümkündür. Tüm döngü komutları, CX registerini kullanarak aşamaları sayar. Bildiğiniz üzere CX register’ı 16 bit’tir ve tutabileceği en büyük sayı 65535 veya FFFFh’dir Ancak, bir atlamaları akıllıca kullanarak 65535 * 65535 * 65535 .... Satırlık döngüler yazmak mümkündür. CX register’ının orijinal değeri PUSH CX komutu ile saklanır. İç döngü bittiğinde ise POP CX komutu ile alınır.
İçiçe döngü örneği ORG 100H MOV BX, 0 ; total step counter. MOV CX, 5 k1: INC BX ; any other instructions PUSH CX k2: k3: ADD BX, 1 ; any other instructions LOOP k3 POP CX LOOP k2 ; internal loop. LOOP k1 ; external loop. RET
Limitler JMP sadece kod sekmanında bir alana atlama yapabilir. Koşullu atlamalar ise sadece 127 bayt ileri veya 128 bayt geriye olabilir. Çoğu komutların üç veya daha fazla bayt olarak assemble edildiğine dikkat ediniz. Bu sınırlama, basit bir yol ile aşılabilir. All conditional jumps have one big limitation, unlike JMP instruction they can only jump 127 bytes forward and 128 bytes backward (note that most instructions are assembled into 3 or more bytes). We can easily avoid this limitation using a cute trick: Get an opposite conditional jump instruction from the table above, make it jump to label_x. Use JMP instruction to jump to desired location. Define label_x: just after the JMP instruction. label_x: - can be any valid label name, but there must not be two or more labels with the same name.
Örnek ORG 100H MOV AL, 5 MOV BL, 5 CMP AL, BL ; JE equal ; unable to jump! JNE not_equal JMP equal not_equal: ADD BL, AL SUB AL, 10 XOR AL, BL JMP skip_data db 256 dup(0) ; 256 bytes skip_data: ; any other instructions here JMP stop equal: stop: RET