assembly programlama-0 ders 3

ibolina

Yeni üye
13 Tem 2008
32
0
Bu bölümde 16 bit bölme yapmayı görecez.
Bölmenin nasıl yapıldı​
ını inceleyelim. Sonra ilemcimize nasıl yaptıracaımıza karar verelim.
8 bit için örnek:
00100100/00000111=00000101 kalan 1

_______​
00100100_/00000111 böleni bir basamak sola kaydırıp bölünenin en soluyla karılatırıyoruz

00000111​
bakıyoruz 00000000'da 00000111 kaç kere var? (ne biçim bi soru bu imdi. Ya 1
kere
vardır ya da yoktur tabii ki :) ) Yok. O zaman bölüneni bir daha sola kaydırıp bakalım.

______​
00100100__/00000111 Yine yok. Böyle devam edelim.

00000111​
__​
00100100______/00000111 Altıncı ilemde görüyoruz ki 00001001 sayısında 00000111 bir kere var ( ehehe ).

​
imdi

00000111​
bunu bölünenden çıkarmamız gerekiyor. Bölünen sayı 00001000 haline geldi.
-------------- Artık böyle devam edecez.

__​
000010

_​
00001000_______/00000111 00001000'da 00000111 yok.

00000111​
00001000​
________/00000111 00001000'da 00000111 bir kere var. Yine çıkarmamızı yapıyoruz. Artık sayımızın
sonuna

00000111​
geldiimiz için daha fazla kaydırma-kontrol etme yapmıyoruz.
-------------- Sonuçta elimizde 00000001 eldesi kaldı. Nihai sonuç da:

00000001​
yok:yok:yok:yok:yok:var:yok:var-->00000101

Umarım herey açıktır. Yukarıya baktı​
ımızda karılatırma gibi çipin tanımadıı bir ilem yapıyoruz. Karılatırmanın amacı
bir sayının bir di
erinden küçük mü büyük mü olduunu anlamak olduundan bu iki sayı ile çıkarma ilemi yaparsak ve
sonuca bakarsak hangisinin daha büyük oldu
unu anlayabiliriz.
Ancak elimizdeki ilemci yalnız 8 bit pozitif tamsayılarla ilem yaptı
ı için bir sorunumuz var.
Negatif sayıları göstermenin bilgisayar dünyasında çeitli yolları vardır. Burada bize gerekli olanı inceleyecez. Öncelikle
sayıları sınırlı bit miktaralarıyla gösterdi
imizi hatırlayalım. Yani bir ilemin sonucu 8 bit bir makinede 8. biti geçerse o ilemin
sonucu genelde oldu
u haliyle kullanılmaz. Carry ve zero flagleri yardımıyla ne yapacaımıza karar veririz.
Bu kadar ara yeter imdi negatif sayıları nasıl gösterdi
imize gelelim. Sayıdan önce 1 çıkarıyoruz. Sonra bütün bitlerin tersini
alıyoruz.
Örnek: -00110110 = 11001010

00110110​
-1=00110101

00​
110101
->11001010

Neden böyle oldu​
unun eminim doyurucu bir matematiksel açıklaması vardır ama burada veremeyecem.
Bir
A sayısı alalım. A sayısının negatifini öyle gösterebiliriz deil mi?: A+(-A)=0

Yukarıdaki örne​
imize bakarsak:

_​
00110101

_​
11001010

+--------------​
1​
00000000

Dokuzuncu bit olmasaydı amacımıza ulamı​
olacaktık ama biz zaten sayıları 8 bitle gösterdiimiz için sorun yok!
Ayrıca
-(-A)=A

11001010​
-1=11001001
11
001001
->00110110

Artık 8 bit ile -128,+127 arasındaki sayıları gösterebiliriz. Bu sayılarla do​
rudan çıkarma yerine negatifini aldıktan sonra
toplama yapabiliriz. 16f628 ve benzeri di
er çiplerdeki SUBWF ve SUBLW komutlarının yaptıı ii buna benzetirsek önemli
sonuçlara varırız:

·​
Negatif aldıktan sonra toplama ileminde elde ettiimiz carry 1 ise çıkarmanın sonucu pozitiftir.

·​
Negatif aldıktan sonra toplama ileminde elde ettiimiz carry 0 ise çıkarmanın sonucu negatiftir.
Ama i
bu kadar basit deil çünkü 00000000'ın tersi yine 00000000. Sonucun negatif olmasının, ilk sayının ikinciden küçük
olmasını "garantilemesini" istiyoruz. Bu sebeple *** ilemcimizde ( burada 16f628a, en azından MPLAB SIM'de ) SUBxx
komutuyla 0'dan 0 çıkarınca carry
1 deerini alır.
Çıkarma ilemine de bakalım. 16 bit çıkarma yaparken low byteların sonucu negatifse borç alma var demektir ( carry=0 ).
Daha önce toplamada yaptı
ımız gibi 256 tabanında düünürsek sonucun high byteından 1 çıkarırız.
Yine toplama yaparken önce sonucun low byteını bulmutuk. Eldeye göre sonucun high byteını 1 arttırıp öyle devam etmitik.
Farketti
iniz gibi ilk deikenin içindeki deer de kaybolmutu. Aslında önce high byteı hesaplayıp sonra low byteların
sonucuna göre düzeltmek daha temiz bir yol oldu
u için toplama ve çıkarmada artık tercih ettiimiz yöntem olacak. Böylece
de
ikenlerden hiçbirini kaybetmeden sonucu baka bir deikene aktarabiliriz. Bölme algoritmasını yazarken nasıl olduunu
göreceksiniz.
Bölme ilemine geldik sonunda. 8 bit bölme yapmak çok sıkıcı olaca
ından direk 16 bite geçtim :). 16 bit sayıyı bir baka 16
bit sayıya bölecez.
Yazının baında bölünenin kendisi kadar daha kayacak yere ihtiyacı oldu
unu gördük. Sonra karılatırma için de geçici bir
de
iken lazım. Karılatırmayı çıkarma ilemiyle yapıp sonucu da buraya yerletiriyoruz. Yalnızca carry biti sonucun negatif
ya da pozitif oldu
unu göstermeye yeter ama eer sonuç pozitifse aynı çıkarmayı tekrar yapmamak için geçici deikenin
içeri
ini kullanabiliriz.
Kodu yazalım:

list​
p=16f628a

#include​
p16f628A.inc

cblock 0x70​
al​
;bolunen low byte

ah​
;bolunen high byte

eal​
;bolunen icin kayacak low byte=0

eah​
;bolunen icin kayacak high byte=0

bl​
;bolen low byte

bh​
;bolen high byte

dl​
;gecici degisken low byte

dh​
;gecici degisken high byte

rl​
;sonuc low byte

rh​
;sonuc high byte

co​
;sayac=16

endc
org 0x0000
goto​
basla

org 0x0005​
bol:​
clrf​
eah ;bolunen icin kayacak yeri temizliyoruz

clrf​
eal

clrf​
rh ;sonucu temizle

clrf​
rl

movlw 0x10
movwf​
co ;sayac=16

lb1:​
rlf​
al,f ;boluneni kaydiriyoruz ki en soldaki parcasini kontrol edebilelim

rlf​
ah,f

rlf​
eal,f

rlf​
eah,f

movf​
bh,w ;buraya dikkat. once bolunenin high byteindan bolenin high byteini cikarip

subwf​
eah,w ;sonucu gecici degiskene yaziyoruz

movwf​
dh

movf​
bl,w ;simdi low bytelarla ayni islem

subwf​
eal,w

movwf​
dl

btfss​
STATUS,C;low bytelarin sonucu negatifse gecici degiskenin high byteini 1 azaltiyoruz

decf​
dh,f

rlf​
rl,f ;karsilastirmanin en son sonucu carryde. bu komutla dogrudan sonuca yazabiliriz

rlf​
rh,f

btfss​
rl,0 ;karsilastirmanin en son sonucu artik carryde degil burada ( sonucun en sag biti )

goto​
lb2

movf​
dl,w ;eger pozitifse bolunenin degerini gecici degiskendeki degerle degistir

movwf​
eal

movf​
dh,w

movwf​
eah
lb2:
;eger negatifse bisey yapma

decfsz​
co,f ;isimiz bitti mi?

goto​
lb1 ;bitmediyse basa don

return​
basla:​
movlw 0x24​
;ah:al=36

movwf​
al

clrf​
ah

movlw 0x5​
;bh:bl=5

movwf​
bl

clrf​
bh

call​
bol ;36/5 sonuc rh:rl ikilisinde kalan eah:eal iklisinde

goto​
$ ;dur

end​
Karılatırmanın sonucunu do​
rudan rlf rl,f ve rlf rh,f komutlarıyla saklamamızın nedeni zaten sonucu soldan saa
doldurmamız. ( Aynen günlük hayatta yaptı
ımız bölme gibi ). anslıyız ki karılatırma sonucu pozitif olduunda carry 1
de
erini alıyor. 0 olsaydı bölmenin sonunda sonucun bitlerini ters çevirmemiz gerekecekti.
Her ne kadar negatif sayılarla ilem yapıyor gibi görünse de aslında algoritmamız sadece pozitif sayıları birbirine bölebilir.
Ayrıca bir sayıyı sıfıra böldü
ünüzde 0xFFFF sonucunu verir. Bu yüzden yukarıdaki kodu olduu gibi kullanırsanız bunlara
dikkat etmelisiniz.
Madem yazdı
ımız çarpma-bölme algoritmları sadece pozitif sayı kabul ediyor biz de negatif sayıları tespit edip pozitife
çevirelim. Kaç bit olursa olsun bir sayıyı negatif kabul ediyorsak en soldaki bitinin daima
1 olması gerekir. 0 ise sayı pozitiftir.
8 bit bir sayıyı -1 ile çarpmak için:

decf​
sayi,f ;(sayi-1)->sayı

comf​
sayi ;bitleri ters cevir

16 bit bir sayıyı -1 ile çarpmak için:​
decf​
sayilow,f ;sayinin low byteindan 1 cikariyoruz

btfss​
STATUS,C;borc alma varsa high bytedan da 1 cikaracaz

decf​
sayihigh,f

comf​
sayihigh

comf​
sayilow ;bitleri ters cevir

Biraz daha fazla kod yazarak artık negatif sayılarla da ilem yapabiliriz. Sonuçları uygun iarete dönütürecek kodları da
unutmayın :).​
Bu seferlik benden bu kadar. Yoruldum, sonra görüürüz...
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.