Bu bölümde 16 bit bölme yapmayı görecez.
Bölmenin nasıl yapıldı
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
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.
kere
vardır ya da yoktur tabii ki
______
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.
-------------- 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
sonuna
00000111
geldiimiz için daha fazla kaydırma-kontrol etme yapmıyoruz.
-------------- Sonuçta elimizde 00000001 eldesi kaldı. Nihai sonuç da:
-------------- 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 dierinden 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 olduunu 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österdiimizi hatırlayalım. Yani bir ilemin sonucu 8 bit bir makinede 8. biti geçerse o ilemin
sonucu genelde olduu 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österdiimize gelelim. Sayıdan önce 1 çıkarıyoruz. Sonra bütün bitlerin tersini
alıyoruz.
Örnek: -00110110 = 11001010
bir sayının bir dierinden 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 olduunu 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österdiimizi hatırlayalım. Yani bir ilemin sonucu 8 bit bir makinede 8. biti geçerse o ilemin
sonucu genelde olduu 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österdiimize 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
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
Ayrıca -(-A)=A
11001010
-1=11001001
11001001->00110110
11001001->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 dier çiplerdeki SUBWF ve SUBLW komutlarının yaptıı ii buna benzetirsek önemli
sonuçlara varırız:
toplama yapabiliriz. 16f628 ve benzeri dier ç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 ibu 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.
Farkettiiniz 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 olduu için toplama ve çıkarmada artık tercih ettiimiz yöntem olacak. Böylece
deikenlerden 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ı olduunu gördük. Sonra karılatırma için de geçici bir
deiken lazım. Karılatırmayı çıkarma ilemiyle yapıp sonucu da buraya yerletiriyoruz. Yalnızca carry biti sonucun negatif
ya da pozitif olduunu göstermeye yeter ama eer sonuç pozitifse aynı çıkarmayı tekrar yapmamak için geçici deikenin
içeriini kullanabiliriz.
Kodu yazalım:
Ama ibu 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.
Farkettiiniz 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 olduu için toplama ve çıkarmada artık tercih ettiimiz yöntem olacak. Böylece
deikenlerden 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
bit sayıya bölecez.
Yazının baında bölünenin kendisi kadar daha kayacak yere ihtiyacı olduunu gördük. Sonra karılatırma için de geçici bir
deiken lazım. Karılatırmayı çıkarma ilemiyle yapıp sonucu da buraya yerletiriyoruz. Yalnızca carry biti sonucun negatif
ya da pozitif olduunu göstermeye yeter ama eer sonuç pozitifse aynı çıkarmayı tekrar yapmamak için geçici deikenin
içeriini 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
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
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
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
deerini 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:
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
deerini 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...unutmayın