Beşiktaş Forum  ( 1903 - 2013 ) Taraftarın Sesi


Geri git   Beşiktaş Forum ( 1903 - 2013 ) Taraftarın Sesi > Eğitim Öğretim > Dersler - Ödevler - Tezler - Konular > Elektronik & Bilgisayar

Cevapla
 
LinkBack Seçenekler Stil
Alt 06-09-2008, 15:14   #11
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

PUBLIC WRITE_CHAR
;................................................. ...............;
;This procedure shows the character in the computer screen using the DOS.
;................................................. ...............;

WRITE_CHAR PROC
PUSH AX ;pushes the value of the register AX in the stack memory
MOV AH,2 ;2h Function
INT 21h ;21h Interruption
POP AX ;Pops the initial value of the register AX to the register AX
RET ;Returns the control of the procedure called
WRITE_CHAR ENDP

END TEST_WRITE_HEX ;finishes the program code
Example 4
This program prints the 256 ASCII code on the screen
;name of the program: four.asm
.model small
.stack
.code

PRINT_ASCII PROC
MOV DL,00h ;moves the value 00h to register DL
MOV CX,255 ;moves the value decimal number 255. this decimal number will be 255 times to print out after the character A
PRINT_LOOP:
CALL WRITE_CHAR ;Prints the characters out
INC DL ;Increases the value of the register DL content
LOOP PRINT_LOOP ;Loop to print out ten characters
MOV AH,4Ch ;4Ch function
INT 21h ;21h Interruption
PRINT_ASCII ENDP ;Finishes the procedure

WRITE_CHAR PROC
MOV AH,2h ;2h function to print character out
INT 21h ;Prints out the character in the register DL
RET ;Returns the control to the procedure called
WRITE_CHAR ENDP ;Finishes the procedure

END PRINT_ASCII ;Finishes the program code
Example 5
This program prints a defined character using an ASCII code on the screen.
dosseg
.model small ; the name of the program is five.asm
.stack
.code
write proc
mov ah,2h;
mov dl,2ah;
int 21h
mov ah,4ch
int 21h
write endp

end write
Example 6
This program reads characters form the keyboard and prints them on the screen until find the return character.
.model small; the name of the program is six.asm
.stack;
.code;

EEL: MOV AH,01 ; 1 function (reads one character from the keyboard)
INT 21h ; 21h interruption
CMP AL,0Dh ; compares the value with 0dh
JNZ EEL ;jumps if no equal of the label eel
MOV AH,2h ; 2 function (prints the character out on the screen)
MOV DL,AL ;moves the value of the register AL to the register DL
INT 21h ;21 interruption
MOV AH,4CH ;4C function (returns the control to the DOS. operating system)
INT 21h ;21 interruption

END ;finishes the program
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:15   #12
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

VERİ İŞLEME KOMUTLARI

Veri işleme komutları iki bölüme ayrılır: Aritmetik ve lojik komutlardır. Bu komutlar bayrakları etkiler. Aşağıda bu komutlar örneklerle anlatılmaktadır.

Aritmetik Komutlar Tablosu

Aşağıdaki tabloda 8051 ailesinin aritmetik komutlarını özetlemektedir. Bu tablodaki bir çok komut, Saklayıcı-Özel adresleme modunu kullanmaktadır.




Gösterim İşlem Adresleme Modları
Dir Ind Reg Imm
ADD A,<byte> A=A+<byte> X X X X
ADDC A,<byte> A=A+<byte>+C X X X X
SUBB A,<byte> A=A-<byte>-C X X X X
INC A A=A+1 Sak.Özel(Sadece ACC)
INC <byte> <byte>=<byte>+1 X X X
INC DPTR DPTR=DPTR+1 Sak.Özel(Sadece DPTR)
DEC A A=A-1 Sak.Özel(Sadece ACC)
DEC <byte> <byte>=<byte>-1 X X X
MUL AB B:A=B*A Sak.Özel(Sadece ACC ve B)
DIV AB A=Int (A/B)
B=Mod(A/B) Sak.Özel(Sadece ACC ve B)
DA A Ondalık Ayar Sak.Özel(Sadece ACC)


















Toplama ve Çıkarma Komutları

İki tane toplama komutu vardır. ADD ve ADDC (C-elde ile topla). Her iki komut 2 byte değişkenin toplama işlemini gerçekleştirmektedir. Birinci operand her zaman ACC'dedir. İkinci operand, doğrudan, dolaylı, saklayıcı veya ivedi adresleme modları ile belirtilir. Bir ADD ve ADDC işlemlerinden sonra, bayraklardan üçü (C,AC ve OV) sonuca göre 1'lenir
Veya 0'lanır.
ADDC komutu, C bayrağının sonuna eklenmesi farkının dışında, ADD komutu gibidir. ADDC komutu, özellikle uzun tamsayı toplamalarında kullanılır.
Yukarıdaki tabloda ve aşağıda verilen program örneğinde, iki 16-bit X ve Y tamsayılarının toplama işleminde (X=X+Y), ADD ve ADDC komutlarının kullanımı gösterilmektedir. Her iki sayı, 8-bit düşük (XL ve YL) ve yüksek değeri (XH ve YH) byte'lar olarak işleme alınmaktadır.





C

ADDC ADD

X

Y
+



İki 16- Bitlik X ve Y tamsayılarının toplama işlemi (X=X+Y).

Bu byte’ların saklayıcılarda aşağıda verildiği gibi saklandığını düşünelim.

--------------------------------------------
Byte Saklayıcı
--------------------------------------------
XL 78H
XH 79H
YL 7AH
YH 7BH
--------------------------------------------
X=1234h ve Y=12EFh tamsayılarını bu hafıza hücrelerine yükleyen program parçası:

MOV 78h, 34h ; XL
MOV 79h, 12h ; XH
MOV 7Ah, 0Efh ; YL
MOV 7Bh, 12h ; YH

XL=XL+YL Toplamını gerçekleştiren program kodu:

MOV A, 78h ; A=XL
ADD A, 7Ah ; A=XL+YL
MOV 78H, A ; XL=A

Yapılan işlemin bu noktasında , 78h adresli hücre 23h değerini içermektedir ve C bayrağı 1’lenmiştir. Şimdi XH=XH+YH+C işlemini gerçekleştiren program parçasına bakalım:

MOV A, 79h ; A=XH
ADDC A, 7BH ; A=XH+YH+C
MOV 79H, A ; XH=A

Bu programın çalıştırılması sonucu,dahili saklayıcı hücreleri 78h ve 79h’ta 2523h değeri doğru olarak saklanır.
Çıkarma işlemi SUBB de ,ACC’yi ilk operand olarak kullanılır.Doğrudan, dolaylı,saklayıcı veya ivedi adresleme modları ile belirtilen ikinci operand, ACC’den çıkartılır ve sonuç yine ACC’ye yerleştirilir.
C bayrağı,uzun tamsayı çıkarma işlemlerinde, toplama işlemine benzer şekilde kullanılır. Çıkarma işlemi,bir ödünç almaya ihtiyaç duyar ise, C bayrağı 1’lenir.
Eğer bir çıkarma işleminden önce, C 1’lenmiş ise,yapılan çıkarma sonucunda bir eksiltilir. Bu sayede, birden fazla byte uzunluğunda olan tamsayıların çıkarma işlemi, en düşük değerli byte’lardan başlayıp yüksek değerli byte’lara doğru, peş peşe byte çıkartma işlemi şeklinde yapılır. Bu durumda , ilk çıkarma işleminden önce C bayrağının sıfırlanması gerekmektedir.
Aşağıda verilen program örneği, iki 16-bit X ve Y tamsayılarının çıkarma işlemini (X=X-Y) göstermektedir. Her iki sayı , 8-bit düşük(XL ve YL) ve yüksek değerlikli (XH ve YH) byte’lar olarak işleme alınmaktadır.
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:16   #13
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

İki 16- Bitlik X ve Y tamsayılarının toplama işlemi (X=X+Y).

Bu byte’ların saklayıcılarda aşağıda verildiği gibi saklandığını düşünelim.

--------------------------------------------
Byte Saklayıcı
--------------------------------------------
XL 78H
XH 79H
YL 7AH
YH 7BH
--------------------------------------------
X=1234h ve Y=12EFh tamsayılarını bu hafıza hücrelerine yükleyen program parçası:

MOV 78h, 34h ; XL
MOV 79h, 12h ; XH
MOV 7Ah, 0Efh ; YL
MOV 7Bh, 12h ; YH

XL=XL+YL Toplamını gerçekleştiren program kodu:

MOV A, 78h ; A=XL
ADD A, 7Ah ; A=XL+YL
MOV 78H, A ; XL=A

Yapılan işlemin bu noktasında , 78h adresli hücre 23h değerini içermektedir ve C bayrağı 1’lenmiştir. Şimdi XH=XH+YH+C işlemini gerçekleştiren program parçasına bakalım:

MOV A, 79h ; A=XH
ADDC A, 7BH ; A=XH+YH+C
MOV 79H, A ; XH=A

Bu programın çalıştırılması sonucu,dahili saklayıcı hücreleri 78h ve 79h’ta 2523h değeri doğru olarak saklanır.
Çıkarma işlemi SUBB de ,ACC’yi ilk operand olarak kullanılır.Doğrudan, dolaylı,saklayıcı veya ivedi adresleme modları ile belirtilen ikinci operand, ACC’den çıkartılır ve sonuç yine ACC’ye yerleştirilir.
C bayrağı,uzun tamsayı çıkarma işlemlerinde, toplama işlemine benzer şekilde kullanılır. Çıkarma işlemi,bir ödünç almaya ihtiyaç duyar ise, C bayrağı 1’lenir.
Eğer bir çıkarma işleminden önce, C 1’lenmiş ise,yapılan çıkarma sonucunda bir eksiltilir. Bu sayede, birden fazla byte uzunluğunda olan tamsayıların çıkarma işlemi, en düşük değerli byte’lardan başlayıp yüksek değerli byte’lara doğru, peş peşe byte çıkartma işlemi şeklinde yapılır. Bu durumda , ilk çıkarma işleminden önce C bayrağının sıfırlanması gerekmektedir.
Aşağıda verilen program örneği, iki 16-bit X ve Y tamsayılarının çıkarma işlemini (X=X-Y) göstermektedir. Her iki sayı , 8-bit düşük(XL ve YL) ve yüksek değerlikli (XH ve YH) byte’lar olarak işleme alınmaktadır.





C





_



İki 16- Bitlik X ve Y tamsayılarının çıkarma işlemi (X=X-Y).



X=1234h ve Y=1135h tamsayılarını hafızaya yükleyen program parçası:
MOV 78h, 34h ; XL
MOV 79h, 12h ; XH
MOV 7Ah, 35h ; YL
MOV 7Bh, 11h ; YH
CLR C ; C bayrağını temizle

XL=XL-YL çıkarma işlemini gerçekleyen program parçası:

MOV A, 78h ; A=XL
SUBB A, 7Ah ; A=XL-YL-0
MOV 78H, A ; XL=A

Bu noktada 78h adresli hücre FFh değerini içermektedir ve C bayrağı 1’lenir. Şimdi XH=XH-YH-C işlemini gerçekleştiren program parçasına bakalım:

MOV A, 79h ; A=XH
SUBB A, 7BH ; A=XH-YH-C
MOV 79h, A ; XH=A

Bu programın çalıştırılması sonucu , dahili saklayıcı hücreleri 78h ve 79h’ta 00FFh değeri doğru olarak saklanır.

Arttırma ve azaltma komutları

Bu komutlar,çevirim sayaçlarını veya veri işaretçilerini arttırma veya azaltma işlemlerinde faydalıdırlar.
Aşağıda verilen bu komutların kullanıldığı bu örnekte,dahili veri hafızada bulunan X veya Y vektörleri (veri blokları) toplanmaktadır.(X=X+Y).Bu programda X ve Y vektörlerinin uzunlukları R3 saklayıcısında olduğu ve ayrıca, X vektörüne R0 Y vektörüne R1 saklayıcılarının işaret ettikleri varsayılmaktadır.

LOOP:
MOV A, @R0 :X ten bir byte oku.
ADD A, @R1 :Y byte'ı topla.
MOV @R0,A :sonucu X e yerleştir.
INC R0 :bir sonraki X byte'ına işaret et.
INC R1 :Bir sonraki Y byte'ına işaret et.
DJNZ R3 , LOOP http://www.supermp3.org/images/smilies/biggrin.giföngü sayacını azalt.sayaç sıfır
:değil ise,LOOP etiketine dallan.

Çarpma bölme komutları

8051 ailesinin üyeleri donanım çarpma ve bölme birimlerine sahiptir.Bu komutlar,4 makine çevrimi ile en uzun zamanı alır.Çarpma ve bölme komutları,saklayıcı-özel komutlar olup ACC ve B saklayıcılarını kullanır.
MUL AB
Komutu,ACC ve B saklayıcılarındaki iki işaretsiz tamsayıyı çarpar.16-bit çarpma sonucunun düşük byte 'ı ACC de ve yüksek byte'ı B saklayıcısında bulunur.Sonuç FFFFh'tan büyük olamaz.Yani C bayrağı hiçbir zaman 1'lenmez.eğer sonuç FFh'tan büyük ise,taşma bayrağı 0V 1'lenir.0V bayrağının sıfırlanması,B saklayıcısının 0 olduğu anlamına gelir.
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:16   #14
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

DIV AB

Komutu ACC'deki 8-bit işaretsiz tamsayıyı B saklayıcısındaki 8-bitlik işaretsiz tamsayıya böler.Sonucun tamsayı kısmı ACC'de,kalan kısmı ise B saklayıcısında tutulur.C bayrağı herzaman temizlenir.Taşma bayrağı 0V, sıfıra bölme durumunu belirtir.Eğer B saklayıcısında bu komuttan önce sıfır bulunursa,sonuç belirsiz olur ve taşma bayrağı 0V 1'lenir.

Ondalık ayarlama(decimal adjust ) Komutu

DA komutu,ikili kodlanmış ondalık (BCD-binary coded decimal) sayılrın toplama işleminden sonra kullanılır.Bir BCD sayının her 4-bit'i (nibble) bir ondalık sayıyı belirtir.Yani,her bir 4-bit'in değeri 0(0000)ile 9(1001) sayıları arasında olabilir.DA komutu ile yapılan işle,ACC ve PSW içeriklerine göre,ACC'ye 0,6,60h veya 66h ekleme işlemi olarak görülebilir.Aşağıdaki örneklerde ,DA komutunun bu özelliği gösterilmektedir.






MOV A,#12h :A=12h (BCD)
MOV B, #29h :B=29h (BCD)
ADD A,B :12h + 29h =3Bh, BCD değil!
DA A http://www.supermp3.org/images/smili...face.gifndalık ayarlama ,burada sonuca 6 eklenir,
:3Bh + 6 = 41h doğru BCD sonuç(12 +29) bulunur.




MOV A,#55h :A=55h (BCD)
MOV B, #66h :B=66h (BCD)
ADD A,B :55h + 66h =BBh, BCD değil!
DA A http://www.supermp3.org/images/smili...face.gifndalık ayarlama ,burada sonuca 66 eklenir,
:BBh + 66 = 121h
:doğru BCD sonuç(55 +66) bulunur.
:ACC,21h (BCD) içermektedir ve
:C bayrağıda 1'lenmiştir.




Gösterim İşlem Adresleme Modları
Dir Ind Reg Imm
ANL A<byte> A=A AND <byte> X X X X
ANL<byte>,A <byte>=<byte> And A X
ANL<byte>,#data <byte>=<byte> And #data X
ORL A,<byte> A=A OR <byte> X X X X
ORL <byte>,A <byte>=<byte> OR A X
ORL <byte>,#data <byte>=<byte> OR #data X
XRL A,<byte> A=A XOR <byte> X X X X
XRL <byte>,A <byte>=<byte> XOR A X
XRL <byte> #data <byte>=<byte> XOR A #data X
CRL A A=00H Sak.özel(ACC)
CPL A A=NOT A Sak.özel(ACC)
RL A ACC’yi bir-bit sola döndür Sak.özel(ACC)
RLC A Sola CY üzerinden döndür Sak.özel(ACC)
RR A ACC’yi bir-bit sağa döndür Sak.özel(ACC)
RRC A Sağa CY üzerinden döndür Sak.özel(ACC)
SWAP A ACC’deki iki 4-bit’i değiştir Sak.özel(ACC)
AND,OR VE XOR Komutları

AND,OR VE XOR Komutlarının hepsi aynı adresleme modunu kullanır.Byte-tabanlı lojik işlemlerinde ,8-bit operand'ların karşılıklı bit'leri üzerinde işlem gerçekleştirilir.Operand'lardan biri,çoğu zaman ,ACC'dir ve aynı zamanda,ACC sonucunsaklandığı hedef saklayıcıdır.İşlem sonucunda hiçbir bayrak etkilemez.


AND ve OR komutları,bir kontrol saklayıcısındaki belirli bitlerin maskelenmesinde (masking) faydalıdırlar.Örneğin PSW'deki diğer bitleri etkilemedensaklayıcı kümesi 3'ün seçilmesini düşünelim.aşağıdaki komutlar PSW'nin 3 ve 4'üncü bitlerinin 1'lenmesini sağlar.

MOV A,#18h :bit 3 ve 4 (00011000b) 1'lenir
ORL PSW,A :saklayıcı kümesi 3 seçilir.

Şimdide saklayıcı kümesi 0 ın seçilmesini sağlayalım.Bu kez,bit 3 ve 4 sıfırlanır.

MOV A,#0E7h :Bit 3ve 4 (11100111b) 0'lanır.
ANL PSW,A :Saklayıcı kümesi 0 seçilir.

Temizle (clear)ve tersle(complement)komutları

Bu komutlar ACC üzerinde işlem yapan saklayıcı-özel komutlardır. CLR A komutu,ACC'nin bütün bitlerini temizler.CPL A komutu ise,ACC'nin her bir bit'inintersini alır.

Döndürme(rotate)komutları

Bu komutlar ACC üzerinde işlem yapan saklayıcı-özel komutlardır.Şekil 6.6'da görülen 4 tane döndürme komutu vardır.Bu komutlar ACC'deki 8-bit sayı veya ACC ve C bayrağındaki 9-bit sayı,sağa veya sola birer bit döndürülür.
Döndürme komutları,maskeleme byte'ları oluşturmada 22nin katları ile çarpma veya bölme işlemlerinde kullanılır.Bit 0'ın sıfır olması sağlanarak ,ACC'yi bir bit sola kaydırma işlemi,ACC'yi 2 ile çarpma işlemine eşittir.Benzeri şekilde peş peşe iki kere sola kaydırma ,ACC'yi 4 ile çapma demektir.Sağa döndürme ise ,2 ile bölme işlemine eşit olur.ikinin katları ile çarpma ve bölme işlemlerinde,MUL ve DIV komutları yerine ,döndürme komutlarının kullanılması işlem hızı açısından önemli kazanç sağlar.



A7 A0
RL

A7 A0
RLC

A7 A0

RR
A7 A0

RRC

Döndürme Komutlarının gösterimi

Karşılıklı Değiştirme (Swap) Komutu

Karşılıklı değiştirme komutu

SWAP A
ACC’ nin 4-bit içeriğinin yerlerini değiştirir. Bu komutla yapılan işlem ACC’ yi 4 kez (her iki yönden birinde) döndürme işlemi olarak ta görülebilir.

Bit-Tabanlı Lojik Komutlar

8051 ailesinin ürünleri, yoğun bit-tabanlı özelliklere sahiptir. Daha önceki bölümlerde bu özelliklerin bir kısmı anlatılmıştı. Tablo 6.6 bit-tabanlı komutların bir özetini vermektedir.


Gösterim işlem
ANL C, bit C bayrağını adreslenen bit ile AND’le
ANL C, /bit C bayrağını adreslenen bitin tersi ile AND’le
ORL C, /bit C bayrağını adreslenen bit ile OR’la
ORL C, /bit C bayrağını adreslenen bitin tersi ile OR’la
CLR C C bayrağını temizle
CLR bit Adreslenen bit’i temizle
CPL C C bayrağını tersle (Complement)
CPL bit Adreslenen bit’i tersle (Complement)
SETB C C bayrağını l’le
SETB bit Adreslenen bit’i l’le


Bit-tabanlı işlemlerde elde bayrağı C, l-bit ACC olarak kullanılır. Örneğin, Tablo 6.6’ dan görüldüğü gibi, birçok bit-tabanlı lojik işlemlerde, C bayrağı, operand’ lardan biri ve sonuç için, hedef l-bit saklayıcı olarak kullanılır.

Bit-tabanlı lojik işlemlerde, kaynak bit’in tersi kullanılmak istenmiyorsa, ‘/’ sembolü kaynak bit’in önüne konur. Bu sembol, kaynat bit’in gerçek değerinin değişmesine neden olmayıp sadece, yapılan işleme, değerinin tersini alınarak girmesine neden olur.

6.5.3 Program Akışı Kontrol Komutları

Dallanma komutları, mikro denetleyicinin yürütme sırasında farklı işlemler yapmasını yönlendiren komutlardır. Örneğin, bir tuşun durumuna veya bir kontrol sinyaline göre, bir motorun durdurulmasını veya çalıştırılmasının devamına karar verme gibi.

Bir dallanma komutu ile, PC’nin içeriği değişip program akışı da değişir. Her komut okuma çevriminde, PC, bir sonraki komuta işaret edecek şekilde yenilenmektedir. Normalde bir sonra yürütülecek komut, hafızada o anki komuttan sonra gelen komut olmaktadır. PC’ nin değişmesi durumunda ise, PC’ deki adresten itibaren program akışı devam eder. Yani hafızada başka bir program alanına dallanma gerçekleştirilmiş olur.

Dallanma komutları, JMP (jump), CALL ve RET (RETurn) komutlarıdır. Bir JMP komutu sadece PC’yi değiştirmektedir. Dallanma komutları, Durumdan Bağımsız (unconditional) ve Duruma Bağımlı (conditional) olmak üzere ikiye ayrılır. 8051 ailesinin mikro denetleyicileri, 3 tane durumdan bağımsız dallanma komutuna sahiptir: SJMP, AJMP ve LJMP.
Durumdan Bağımsız Dallanma Komutları

Aşağıdaki Tablo 3.7’de Durumdan Bağımsız Dallanma komutlarının bir özeti verilmektedir. Bu komutların her biri ile gerçekleşen program akışındaki dallanma, PC içeriğinin değişmesiyle olur. Tabloda verilen ilk 3 dallanma komutu birbirine benzemektedir. Verilen en son indisli dallanma komutu ise, ACC ile DPTR’ ın içeriklerini toplayıp bir sonra okunacak ve yürütülecek komutun adresini hesaplayan güçlü bir komuttur.


Gösterim Açıklama
SJMP <rel add> (Short Jump- Kısa Dallanma) Operand, 2-nin
tümleyeni tek bir byte olup değeri PC’ ya ekle-
nir. Bir sonraki komut, 127 byte ileri veya 128
byte gerideki bir komut olacaktır.
AJMP<Address ll> (Absolute Jump-Mutlak Dallanma) Operand,
ll-bit bir adres olup Program Hafızanın o anki
2 Kbyte’lık alanı içine karşı gelir.
LJMP<Address 16> (Long jump-Uzun Dallanma) Operand, l6-bit
bir adres olup Program Hafızasının 64 Kbyte’lık
alanı içinde bir yere karşı gelir.
LJMP A+DPTR
**eksik**var (Long jump-Uzun Dallanma) Yürütülecek bir
sonraki komutun adresi, ACC ile DPTR’ ın
toplamıdır.
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:17   #15
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

Kısa ve Uzun Dallanmalar

Kısa dallanma komutları, genelde bir altprogramın içinde kullanılır. Bu komutlarda dallanacak alan, dallanma komutunu takip eden 127 byte ilerisi ile 128 byte gerisi, arasında sınırlıdır. Dallanma adresi, bir sonraki komuta göre göreceli (relative) ofset olarak tanımlı olduğu için, program kodu başka bir adrese tekrar taşınabilir durumdadır (relocatabla code). Bir program veya bir blok kod, program hafızada yerleştirildiği yerden bağımsız olarak doğru çalışıyorsa, tekrar yerleştirilebilir (relocatable) diye adlandırılır. Kodun tekrar yerleştirilebilir olmaözelliği, dallanma komutları kullanıldığında önemli olur. Eğer bir dallanma komutu, program akışını Program Hafızada belli bir adrese yönlendirirse dallanma adresinde geçerli bir kodun olması programcının sorumluluğundadır. Kısa dallanma komutları kullanılan bir kod bloğunun, hafızada bir başka adrese taşınması durumunda, program, yerleştirildiği yerden bağımsız olarak düzgün çalışacaktır. Çünkü, bir dallanma adresi sonraki komuta göre, göreceli ofset olarak hesaplanır. Aşağıda verilen program parçasını düşünelim:

ORG 8000h
MOV C, P0.0
MOV Pl.0, C
LJMP 8000h ; tekrar

Bu program 8000h adresinden itibaren yerleştirilmelidir. Çünkü , son komut 8000h adresine bir dallanma yapar. Eğer program başka bir adrese yerleştirildiyse, doğru çalışmayacaktır. Şimdide aşağıdaki değişiklikle programa bakalım:


ORG 8000h

START:

MOV C,P0.0
MOV P1.0, C
SJMP START ;TEKRAR


Bu durumda başlangıç (ORG-origin) adresi değiştirilse de program doğru olarak çalışacaktır. Yukarıda verilen üç komutun her biri 2 byte uzunluğundadır. Program başlarken PC 8000h değerindedir ve sırasıyla 8002h ve son komut yürütülmeden 8004h değerini alır. Son komut ta 2 byte uzunluğunda olduğu için , PC artırılarak 8006h olur. Bununla beraber ,son komut bir dallanma komutu olduğu için , PC değerinin göreceli 6 byte gerisindeki adres olan 8000h değeri PC’nin değeri olur. Böylece, işlemci sonsuz bir çevirim içinde çalışmasına devam eder. Eğer program başlangıç adresi değiştirilse , örneğin , 9000h yapılsa; program yine doğru çalışacaktır. Komutlar 9000h , 9002h ve 9004h adreslerinden başlar ve son komut yürütüldüğünde, PC 9000h adresinden başlayarak çevirim tekrar eder.programın kısa dallanmalı ikinci şekli, Program Hafızada tekrar yerleştirilebilir olup birinci verilen örnek , hafıza –özeldir.

Yukarıdaki örnekleri genelleştirecek olursak,uzun dallanmalar kullanan programlar hafıza-özeldir.Buna karşın, kısa dallanmalar kullananlar ise, tekrar yerleştirilebilir programlardır.Uzun dallanmalara,bilhassa,kod boyunun kısa dallanmaların alanı dışına taşması durumlarında ihtiyaç vardır.Program geliştirmede genel bir yaklaşım, kod üretimindeki derleme(assembly) ve kod bağlama(link) işlemlerinin ayrılmasıdır. Derlemede, uzun dallanmaları takip eden adresler gibi , bazı özel adresler haricindeki assembly kodu büyük bir kısmı makine diline çevrilir. Derlenen kod segmentleri ve alt programlar , daha sonra bir linker programı ile bağlanarak en son yürütülecek program elde edilir. Bu bağlama aşama ,dallanma adreslerine harici referansların değerleri ve değişkenlerin değerleri belirlenir.

Mutlak (absolute) Dallanma

8051’in mutlak (absolute) dallanma komutu (AJMP) , derleme ve bağlama işlemlerini ayırmaya bir alternatif sunarak , kod için bir çeşit tekrar yerleştirilebilirlik sunmaktadır. Mutlak dallanmalar, dallanma adresinin en düşük değerli 11-bit’ini tanımlar.
Iste internette bircok sitede, formda gördügüm bu cümle. HAYIR Assembler ölmedi ve ölemezde! Assembler bugünde tipki yillar öncesindeki gibi önemli bir dil. Makine yakini hizli, kücük programlar üretmek icin en iyi dil. >> Neden Assembler? C/C++ da makine yakini, kücük ve gercekten hizli programlar üretebiliyor. << diyorsaniz ve eger yeni bir isletim sistemi veya sürücü yazmak istemiyorsaniz, hakli oldugunuzu itiraf etmeliyim. Ama bugun bile bazi yerlerde derleyicilerden daha iyi programlari optime etmek mümkün. Bunun disinda Assembler ile programlamak size bilgisayarla tam bir iletisim kurma imkani veriyor. Yani yazdiginiz her komut, bilgisayarin CPU(FPU komutlari haric) tarafindan direkt olarak calistiriliyor. Ilk bölümde daha önce Bilgisayar donanimi hakkinda yada CPU ve FPU hakkinda fazla bilgi sayibi olmayan insan lara bu donanim parcalari hakinda bilgi verecegim.

Her bilgisayar bir CPU ya sahiptir. CPU lar farkli bicimlerde olabilirler. Su an kullanilan CPU lar genelde iki bicimdelerdir. RISC ve CISC CPU lar. CISC 8086 tabanli islemcilerin kullandiklari komut modelidir. RISC komut destekli CPU lar ise genelde Server ve Workstation larda kullanilirlar. RISC az bir komut kapestesine ve az sapida adresleme modellerine sahiptir. Genelde her komut bir Takt da yapilir. Hatta bazi durumlarda bir Takt icinde bir kac islem yapmakta mümkündür. CISC CPU lar ise bir CPU ne kadar komut taniyorsa o kadar iyidir, felsefesi üzerine yapilirlar. Bazi komutlar 10 Takt bile gerektrebilirler. Ama yeni CISC CPU lari ile CISC ile RISC arasinda fazla bir fark kalmamistir. Cogu CISC CPU usu günümüzde CISC komutlarini kücük RISC komutlari haline getirip calistirabilme özelliginin yani sira 1 Takt da bir kac islem yapma özzelliginede sahiplerdir. Bunun disinda yeni bir islemci modeli olan EPIC (CISC ile RISC in karisimi) de intel tarafindan IA64 ile su anda pazara yerlestirilmeye calisiliyor. Ama genel bir CPU her sekilde registerlere, ve bir adresleme bicimine sahiptir.
CPU:
Datenbus

----------------------------------
^....-REGISTERS-.-.............
|...............|..........-.................
|...............|.........-..................
|...............|........-...................
|...............|.......-....................
|...............|......-.....................
|...............|...- . . OP-Code.
---------ALU-------BR .. BZ
Flags...... |...........................
----------------------------------
Adressbus

ALU bir islemcinin kalbidir denebilir. Islemler ALU icinde gerceklesir. Adressbus bize herhangibi bir alani adresleme olanagi verir. Datenbus üzerinden veri degis tokusu olur. Registerler bir islemcinin en önemli parcalaridirlar.Islemlerin yapilabilmesi icin ihtiyac duyulurlar, ve her hangibibir veri den cok daha hizli erisilebilirler. FPU ya gelince. FPU da CPU gibi kendi register lerini icerir ve kendi komut satiri vardir. Yüksek, komali vs. sayilarin hesaplanmasinda CPU dan cok daha hizlidir. 8486 dan beri FPU CPU un bir parcasi olarak bulunuyor. FPU ile programlamayi bu dökümanda ögrenmeyeceksiniz. Ama talep gelirse bu konu hakkindada bir döküman hazirlayabilirim.
Merhaba Dünya!

--------------------------------------------------------------------------------
Bircok kitaptaki gibi bizde önce bir “Merhaba Dünya!” programiyla Assembler diline girelim. Derliyici olarak aksi söylenmedigi sürece TASM kullanilacaktir.(Zaten MASM ile TASM arasinda bir fark oldugu söylenemez)

.model small

.data
merhaba db ‘Merhaba Dunya!$’
.code

start:
mov ax, @data
mov ds, ax

mov ah, 0x09
lea dx, merhaba
int 0x021

mov ah, 0x04c
int 0x021

end start
ends


Aslinda ilk bakista fazla cana yakin bir dile benzemiyor Assembler, ama anlayinca gercektende kolay oldugunu anlayacaksiniz. Anlatmaya basliyorum;
Öncelikle “.model small” komutu ile programin programin bir CS(Code Segment) ve bir DS(Data Segment) e sahip olacagini söylüyoruz.SS(Stack Segment) ile DS ne yazikki ayni yeri paylasiyorlar. Daha sonra “.data” ile degiskenlerin saklanacaklari yeri belirliyoruz. DB(Define Byte) ile satirimizin Byte lar halinde saklanan bir degisken olmasini istedigimizi belirtiyoruz. “.code” ile CS e girdigimizi söylüyoruz. “mov ax, @data” ve “mov ds, ax” ile önce AX e DS nin baslangic adresini yükleyip sonrada DS in baslangic adresini AX den DS e yüklüyoruz. Bu cok önemli cünkü 8086 Segment ve Offset lerle adreslemeye izin veriyor. “mov ah, 0x09” ilea ax registerinin üst 8 Bittine 9 degerini yüklüyoruz. “int 0x21” ile bu DOS icin ds:dx adresindeki satiri yaz anlamina geliyor. Tabi adresin offset kismini dx e “lea” ile yüklüyoruz. Sonrada yine ah ye 0x04c yükleyerek int 0x21 i cagiriyoruz, buda DOS icin “Program bitti CIK!” demek oluyor. Simdi gelelim NE DEMEK Segment NE DEMEK Offset isine. 8086 islemcisi 20 Bitlik bir Adressbus a sayipti. Yani 1MB lik adresleme olanagina. Ama sadece 16 Bitlik registerleri vardi, bu yüzden INTEL aklina gelen süper(Ne kadar süper oldugu tartisilamaz tabi) bir fikri hayata sundu. Buna göre adresler söyle hesaplaniyordu: Adres= 16*Segment+Offset Mesela havisada F6000 adresine ulasilmak istendiginde bu ister bu adresi F600:0000 olarak ister F000:6000 seklinde yazibilisiniz. Birinci kisimda Segment ikinci kisimda ise Offset in bulunmasi gerekiyor. Iste size 8086 nin registerleri:

8086:

ax ah al
bx bh bl
cx ch cl
dx dh dl

cs: ip
ds: di
es: si
fs
gs
ss: bp, sp

Flags

Aslinda 8086 nin gercektende az registere sahip oldugunu söyleyebiliriz. Ax, bx, cx, dx genel amacli registerlerdir. Cs, ds, es, fs, gs, ss adreslemede Segment kisminda kullanilabilir ip, di, si, bp ve sp ise offset kisminda kullanilabilirler. Bunun disinda her register 16- Bit boyutunda ve ax, bx, cx, dx registerleri üst ve alt kisimlari seklindede kullanmak bümkün. H üst 8 Bit L ise alt 8Bit icindir. Bu sekilde mesela ax registerine hem 6 hemde 4 degerini tutacak sekilde verebiliriz. Örnek:
mov ah, 6
mov al, 4
; iki degerde ax registerinin icinde bulunuyor.
Programcilar icin bir diger önemli gelisme ise 8386 ile gerceklesti. Bu islemci ilk IA32 destekli islemci olmakla beraber, kendi 32-Bitlik registerlerini sunuyordu. Hemde bu islemci üzerinde her registeri her islem icin kullanmak mümkün. Tabi CS ile EIP disinda. Cünkü CS:EIP programin o anda bulundugu durumu, yani bir sonraki komutun adresini tutar. Iste 8386 nin registerleri:

8386:

eax ax ah al
ebx bx bh bl
ecx cx ch cl
edx dx dh dl
cs
ds
es
fs
gs
ss
eip ip
edi di
esi si
ebp bp
esp sp
eflags

Önünde e harfi olan registerler 32 Bitlikler. Ve 8386 sayesinde artik adreslemek icin Segment lere ihtiyacimiz yok, 20 Bitlik adres kapestesi yerine 32- Bitlik bir adres kapestesi var 8386 nin, ve bu adresler tam bir registere sigiyorlar, yani 1MB lik adres kapestesi 4GB seviyesinde artik!

Eski(8086):
Merhaba db ‚Merhaba Dunya!’
lds di, merhaba
; merhaba nin adresi= ds:di

Simdi(8386)
Merhaba db ‘Merhaba Dunya!’
lea edi, merhaba
; merhabanin adresi= edi

Simdilik öncelikle en önemli Assembler komutlarini burda kisaca bir aciklayayim:
“mov register/segment/degisken, register/segment/degisken” virgülden önceki kisma, virgülden sonraki kismi yükler. Önemli olan ve dikkat edilmesi gereken en az bir tane registerin verilmis olmasi. Daha sonraki en önemli komutlar ise Matamatik komutlari. “add” toplama, “sub” cikarma “mul” carpma ve “div” bölme icindir.
Mesela deger1= deger2*16;
Assembler:
mov ax, deger2
shl ax, 4
mov deger1, ax
Burada dikkatinizi ceken komut “shl” olabilir. Shl belirtelen sekilde bitlerin sola kaydirir, fakat capma islemlerindede kullanilabilirler, üstelik mul dan 4-5 kat daha hizli calisirlar. 1 degerinde kaydirmak 2 ile capmak, 2 degerinde kaydirmak 4 ile carpmak , vs seklinde devam eder. Tabi matamatik komutlarini “lea” ile gerceklestirmekte mümkün, tabi 8386 dan itibaren, nasilmi? 8386 da her registerle adresleyebildigimizi söylemistim, artik cs, sp gibi registerleri kullanmak zorunda degiliz. Bu yüzden, simdik su komutun ne yaptigina bir bakalim:
lea eax, [eax+eax*4]
Bu komut eax e eax+eax*4 ün icerigini yüklüyor. Ama bu eax ile 5 in carpimindan baska bir sey degil!
mov ecx, eax
shl eax, 2
add eax, ecx
Burda “lea” ile sadece 3 satiri 1 satir haline getirmekle kalmiyoruz ayni zamanda bir registerin kullaniminida engellemis oluyoruz. Bu kadar derinlere girdikten sonra simdik kaldigimiz yerden devam edelim. Ilk programda “merhaba db ‘Merhaba Dunya!$” satirinda dikkatinizi ‘$’ cekmisdir herhalde. Bu isaret Dos icin cok önemli, satirin sonunu belirtiyor. Windows da 0 ile satir sonu belli edilebiliyor. Simdik en basta yazdigimiz “Merhaba Dünya!” programini birde Windows icin yazalim;
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:18   #16
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

Includelib import32.lib ;
Windows fonksiyonlari icin

.386
; 8386 nin registerlerine ve
;komutlarina ihtiyacimiz var!
.model flat, stdcall
; 32- Bit adresleme(4GB!)

extrn MessageBoxA : Proc
extrn ExitProcess : Proc

.data
Caption db „Merhaba Dunya!“,0
Text db “MERHABA!”, 0
.code
start:
push 64
push Caption
push Text
push 0
call MessageBoxA ; MsgBox göster
call ExitProcess ; cik
end start
ends
Yukaridaki programda push ile fonksiyonlara verileri gönderdik. Normalde push ladiginiz herseyi pop lamalisinizda, ama bu örnekte ExitProcess zaten bir degisken beklemedigi icin bu bir sorun yaratmiyor, neyse bu tek Windows programiydi bu kitap icerisindeki, daha fazlasi icin Windows API isini ögrenmeniz gerekiyor. Bunun disinda diger DOS programlarinda kullandigimiz “mov ax, @data”, “mov ds, ax” satirlarinida kullanmamiz gerekmiyor, cünkü adresle tek bir registere sigdiklari icin Segment lere ihtiyacimiz olmuyor.
Programlamaya kaldigimiz yerden devam edelim,
Size bir kac Tipp vereyim;
Carpma ve bölme islemleri icin shl ve shr yi kullanin.
Bir sayi 0 a esit olup olmadigini kontrol ederken cmp ax, 0 yerine test ax, ax i kullanin.
CMOVcc ve SETcc yi programlarinizda kullanin.
Bir sayiya 0 yüklemek isterken mov ax, 0 yerine xor ax, ax i kullanin. Bir sayiya bir eklerken inc bir cikarirken dec i kullanin.

Bir kac altin tipten sonra simdikte iki sayiyi toplayan, basit bir program yazalim;

sayi_bir equ 0x18 ; 24
sayi_iki equ 0x5 ; 5
sonuc equ ax

.model small
.stack 0x100 ; 256 Bytes yeter
.code
start:

mov ax, sayi_bir
add ax, sayi_iki

mov ah, 0x9
int 0x21
end start
ends

Bu programda sayi_bir, sayi_iki ve sonuc birer degisken degil sadece equ ile isimlendirilmislerdir. Daha önce C ile programladiysaniz EQU nun #define ile ayni oldugunu size söyleyebilirim. Bir diger önemli komut ise CMP komutudur. Degerleri karsilastirir ama kaydetmez bunun yerine Flag lari degistirir. Cmp nin kullanim sekli söyledir;
Örnek:
cmp ax, 2
Bu komuttan sonra cmp önce ax 2 ye essitmi diye bakar., esitse zero-flag (zf) doldurur, sonra da kücük büyük denemesi yapar. Kücük ise SF=OF büyük ise SF!=OF degerlerini gönderir.
Örnek:

.model small
.code
start:

cmp ax, 4
jge kucuk
jl buyuk
je esit
jmp son

kucuk:
inc ax
jmp son

buyuk:
dec ax
jmp son

esit:
add ax, ax

son:
mov ah, 0x09
int 0x21
end start
ends

Böylece degerleri karsilastirabiliriz. Üstekki program 8086 icin yazildi. Pentium Pro icin optime edildiginde söyle bir kod cikacaktir:
.686
.model small
.code
start:
cmp ax, 4
cmovge cx, 1
cmovl cx, -1
cmove cx, ax
add ax, cx
mov ah, 0x09
int 0x21
end start
ends

seklinde cok daha kisa, ve performans bakimindan cok daha yüksek bir program elde edecegiz, iste bu tip Optime olaylari bize Assembler ile gerceklestirilirken bütün diger dillerden daha cok kolaylik sagliyor bize. VC++ 6.0 hayla cmove, csete gibi komutlari desteklemiyor, yukaridaki kodu bir VC++ 7.0(.Net) derliyicisiyle elde etmeniz mümkün.
Kaldigimiz yerden devam edelim yukaridaki kod ne anlama geliyor; iste C/C++ veya Java bilenler icin:
if(ax<4) ax++;
else if(ax>4) ax--;
else if(ax==4) ax = ax*2;
Yada herkesin anliyacagi bir bicimde:
Eger(ax 4den kücükse) ax i bir degerinde arttir.
Eger(ax 4den büyükse) ax i bir degerinde azalt.
Eger(ax 4 e esitse) ax i 2 ile carp.
Bunun disinda ziplama komutlari dilin en önemli yapi taslarini olusturmaktadirlar. Hicbir Flag a bakmazsizin ziplama JMP komutu ile yapilir. Daha sonra Jcc(cc yerine herhangibi harfler gelebilirler) seklinde belli flaglar doldurulduklarinda yada silindiklerinde sadece ziplama yapan komutlar vardir. Bir ziplama komutunu ister bir label in adini ister bir adresi yazarak kullanabilirsiniz. Simdi buraya kadar gördügümüz ziplama komutlarina bakalim:
JE = Eger ZF dolu ise ziplar.
JLE= Eger SF OF den farkli ise ziplar.
JGE= Eger SF OF ye esitse ziplar.
Bunun disinda simdi yeni baslayanlara birkac Tipp daha vereyim:
Mümkün oldugunca az ziplama komutlarini kullanin. Mümkün oldugunca az sekilde registerlerin alt, ve üst kisimlariyla ayri seklide calisin. Mesela ah ye 2 ve al ye 4 degerini yüklemek istediginizde:
mov ah, 2
mov al, 4
Yerine;
mov ax, 0x0204
yazarak programinizin icindeki bir islemin hizini 2 Kat daha hizli halledebilirsiniz.
Eger 8086 icin programlamak zorunda degilseniz CMOVcc, SETcc ve MMX i kullanmaktan kacinmayin.Degerleri DX:AX icine saklamak yerine 32- Bitlik registerleri kullanin. FPU yu kullandiktan(dagittiktan) sonra tekrar toplamayi unutmayin. Bu size ve diger programcilara yardim eder. Eger 32- Bit programliyorsaniz her registeri her is icin kullanmaktan kacinmayin. Ama Windows icin programliyorsaniz EBX, EDI, ESI ve EBP nin degerlerini degistirmeden önce yedeklemeniz gerekmekte. Bunu su sekilde yapabilirsiniz:
push ebp
push edi
push esi
push ebx
; Burada registerleri kullanabilirsiniz.
; ….
pop ebx
pop esi
pop edi
pop ebp

Burda gördügünüz gibi PUSH stack’a(Yada havisaya) deger itmek icin kullanilirken, POP da deger cekmek icin kullanilir. Neden ilk ebp nin itilipte en son cekildigine gelince: Biz dokunmadan önce bos bir havisa rutini (Stack):

BP
SP

Simdi önce iki degeri push liyalim.

push 3
push ds

Su anda Stack söyle gözüküyor:

BP
3
DS
SP

Eger bir degeri pop larsak stack in en basindaki elemani cekiyoruz demektir. Yani:


pop ax ; ax= 3
pop es ; es=ds

Ve bu komuttan sonra Stack yine su sekilde gözüküyor:


BP
SP

Unutmayin SP herzaman Stackin sonunu BP ise basini tutar. Ayni zamanda BP fonksiyonlarda elemanlara erismek icinde kullanilir. Aslinda fonksiyonlar bir cok sekilde yaratilma imkani sunarlar ki bunlardan bazilari su sekildedirler:
topla proc near
push ebp
mov ebp, esp
mov eax, [ebp+4]
add eax, [ebp+8]
leave
ret
endp

yada;

topla:
push ebp
mov ebp, esp
mov eax, [ebp+4]
add eax, [ebp+8]
pop bp
ret

yada;

topla:
mov eax, [esp+4]
add eax, [esp+8]
ret

En alttaki sekil size biraz yabanci gelebilir, cünkü derliyiciler tarafindan fazla kullanilmaz. Bunun disinda ebp+4 ün ikinci ebp+8 ise birinci deger oldugunu unutmayin. Bunun sebebi Stackin yukaridan asagi dogru gitmasidir.Yani esp+8, esp+4 den daha önce push ile itilmistir. Bu yüzden birinci degerdir. Ama C/C++ da ikinci deger! Cünkü C/C++ Stack a biraz baska bir acidan bakar ve ilk push ile itilen degeri en son, en sonda push lanan degeri ise ilk deger olarak görür. Bunun disinda söyle bir fonksiyonun yapisina bakildiginda:

topla proc near
push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, [ebp+12]
pop ebp
ret

Bu yukardaki fonksiyon C/C++ de su sekilde yazilabilir:
int topla(int sayi1, int sayi2)
{
return sayi1+sayi2;
}

Ama eger size gelen verinin icerigini degistirmek istiyorsaniz,
Java da;

public static
void topla(int sayi1, int sayi2)
{
sayi1+=sayi2;
}

Ilk bakista bu koddan yola cikarak asagidaki kodu yazarsak gercekten bir yanlis yapmis oluruz;
void topla(int sayi1, int sayi2)
{
sayi1+=sayi2;
}
C/C++ ile programlayanlar yukardaki kodun, size hicbirsey kazandirmadigini bilirler, bu ayni sekilde Assembler dilindede böyledir, eger toplama islemini bu sekilde yapmak istiyorsaniz, iki yolunuz var:

void topla(int *sayi1, int sayi2)
{
*sayi1+= sayi2;
}

yada C++ da;

void topla(int &sayi1, int sayi2)
{
sayi1+=sayi2;
}

ikiside ayni Assembler Kodunu yaratirlar;

topla proc near
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov edx, [ebp+12]
add [eax], edx
pop ebp
ret
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:18   #17
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

Burada ilk dikkatinizi ceken “add [eax], ecx” kod parcasi olmali, bu kod C/C++ da “*eax+=ecx” ile aynidir. Yani size gelen degeri degistirmek yerine, size gelen degeri tasiyan degiskeni degistiriyoruz burda. Yani eger bir deger, yada register parantez icinde ise, o registerin icindeki deger degil, gösterdigi adresdeki deger önemli demektir. Dikkat edin yukardaki fonksiyonu su sekilde cagiramazsiniz;
push 12
push 6
call topla
Böyle bir kodda siz eax in icine 0x06 adresini yüklersiniz, ve programiniz bu yüzden hata cikartir. Cünkü “topla” fonksiyonu 0x06 adresindeki veriyi degistirmeye calisir. Böyle bir fonksiyon su sekilde kullanilir;

lea eax, degisken
push 12
push eax
call topla

Bu durumda fonksiyona degiskenin adresi gönderilir(°isken) ve fonksiyonda bu degeri degistirmesi beklenir.Degisken icin tanimladigimiz bir degisken, yada Stack dan bir degisken koyabiliriz. Bunun disinda Assembler dilinde bir döngü yapmak icinde bir kac yöntem bulunmakta, iste iki temel döngü sekli:

dongu:
cmp ax, cx
je devam_et
dec cx
jne dongu

devam_et :
;...
Yukaridaki kod C/C+ da;
while(cx!=ax) cx--;
Seklinde yazilabilir. Bu cx, ax e esit olmadigi sürece cx den bir cikar anlamina geliyor. Ama bir dongunun cx sifir olana kadar devam etmesini isterseniz;
while(cx!=0) cx--;
Seklinde bir kod parcasina derleyici size baska bir kod parcasi gösterecektir;
dongu:
loop dongu
; …
Seklinde olacaktir kodunuz. „loop“ komuttu cx sifir oalana kadar donguyu devam ettirir, her seferinde cx den bir cikarir. Mesela;
while(cx!=0) { ax++; cx-- }
su sekilde derlenir;
dongu:
inc ax
loop dongu
; …
Tabikki derliyicinizin yukaridaki koddan daha degisik bir kod da vermesi dogal olacaktir, nede olsa C/C++ da registerlerle degil, degiskenlerle ugrasir programci, eger derleyici yeterli bir optime islemi yapmayi basarirsa elinize yukardaki kod gecer. Son olarakta SETcc hakkinda kücük bir kod örnegi yazayim ;
mov ax, 0x00FF
mov dx, 0xFF00
; dx :ax= 0xFF0000FF
add ax, 0xFF00
setc dl

Yukaridaki kod ne yapar? DX:AX in icine 32- Bitlik bir sayi yazar, daha sonra bu sayinin alt 16- Bittini 0xFF00 ile toplar. Eger sonuc sigmazsa dl nin icine 0x01 degerini yükler, böylece toplama islemi sorunsuzca gerceklesmis olur.
Not: Yukaridaki kod sonuc bilindigi icin yazildi, eger böyle bir koda programinizda ihtiyac duyuyorsaniz, asadaki sekilde yazin:
add ax, 0xFF00
adc dx, 0
Böylelikle isinizi riske atmamis olursunuz
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:18   #18
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

Tabikki Setcc nin gücünü gösteren Örnek bir kodda yazmak mümkün, mesela asadakki gibi cok fazla kosulun oldugu program parcasinda, C++:

if(r1==r2) r1++;
else if(r2==r1) r2++;
else r1=r2;
if(r1==r2) r1--;
if(r2==r1) r2--;
else if(r2==(r1-1)) r3=r2;
else r2=r3;

Assembler x86:
if0:
Cmp ax, bx
Jne else_if0
Inc ax
Jmp if1
else_if0:
Cmp bx, ax
Jne else0
Inc bx
Jmp if1
else0:
Mov ax, bx
if1:
Cmp r1, r2
Jne if2
Dec ax
if2:
Cmp bx, ax
Jne else_if1
Dec bx
else_if1:
Mov cx, bx
Dec cx
Cmp ax, cx
Jne else1
Mov cx, bx
Jmp cnt
else1:
Mov bx, cx
cnt:
;...

Burda Cmov ve Set komutlarini kullanarak yüksek bir seviyede performans elde ediyoruz, cünkü sadece 4 kere zipliyoruz. Yukarida ise 8 kere.

xor ecx, ecx

cmp eax, edx
jne else_if1
inc eax
jmp if_1
else_if1:
cmp edx, eax
sete cl
cmovne eax, edx
add eax, ecx
if_1:
cmp eax, edx
sete cl
sub eax, ecx
cmp edx, eax
jne else_if2
dec edx
jmp end_if
else_if2:
mov ecx, eax
dec ecx
cmp edx, ecx
xor ecx, ecx
cmove ecx, edx
cmovne edx, ecx
end_if:
Yukaridaki Cmov ve Set ile yazilmis olan kod x86 icin yazilmis koddan cok daha hizli(Tabikki Pentium Pro icin), ziplama komutlari kullanilmadigi icin, islemcinin bir sonraki komutu tespit etme imkani daha yüksek. Bunun disinda ziplama olmadigi icin koddaki CS:EIP register ciftlerinin icerigide degistirilmiyor. Unutmayin Set komutu 8386 dan Cmov komutu ise Pentium Pro dan itibaren gecirlidir.
Eger Assembler i ögrenmek istiyorsaniz, BIOS int. lerini ögrenmelisiniz. Ama eger Dos icin program yapmak(yazmak) istiyorsaniz Dos cagrilarini, Windows icin program yapmak(yazmak) istiyorsaniz Windows API isini ögrenmelisiniz. Ama BIOS int. lerini kesinlikle ögrenmeniz gerekmekte, bunlar size er yada gec lazim olacaktirlar.(Meselaa bir isletim sistemi yazmak istediginizde!)
Yüksek sayilarla calismak

--------------------------------------------------------------------------------
Bir cok dilde 64-Bitlik veri tiplerine raslamak dogal, oysa x86 islemcilerinin 64 Bitlik registerleri bulunmuyor, peki nasil oluyor bu? Öncelikle ilk akla gelen cevap 64-Bit lik bir sayinin 32 Bitinin bir resistere, diger 32 Bittin baska baska bir resistere yüklenmesi. Bu VC++ deki __int64 ile tanimlanabilen veri türü ile ayni islemin yapilmasi anlamina geliyor. Mesela:
mov eax, 0x00ffff00
mov edx, 0x000000ff
Seklinde 0x000000ff00ffff00
(1095233437440) sayisini eax:edx in icine kaydediyoruz. Mesela basit bir toplama islemini su sekilde yapiyoruz,
add eax, eax
adc edx, edx
Burda 1095233437440 sayisini kendisi ile topladik(yada iki ile carptik). Adc komutu add dan farkli olarak önce sayiyi topluyor sonrada üstüne CF in degerini ekliyor. Akla gelen ikinci yöntem ise FPU, bu sayede C/C++ da double adi verilen sayilarla carisma olanagimiz oluyor. 3 üncü ve en iyi tekniklerden biride MMX. MMX 8 tane 64-Bitlik register le geliyor.(MM0…MM7) Ama bu registerler yeni degiller, aksine eski 80-Bitlik FPU registerlerini(ST0…ST7) kullaniyorlar. Ama yaninda bu sayilari islemek icin bircok yeni komutla beraber geliyor MMX, ve bu sekilde sadece bir register icinde bir sayi ile calismak zorunda degiliz. Herhangibir registerin icine 8 tane sayi koyup, 8 ile ayni anda calismamiz bile mümkün. Ama yinede MMX inde eksikleri var, ama bunlar 3Dnow! SSE ve SSE2 ile ortadan kalkmis durumdalar. Yinede size su anda MMX ile calismanizi tavsiye ederim, cünkü hem 3DNow, hem SSE hemde SSE2 MMX i destekliyorlar. Ama su anda SSE2 sadece Pentium 4 tarafindan destekleniyor. TIP: Sayilarin hesaplanmasinda Windows un hesap makinesi, gelismis bölümünü kullanabilirsiniz. Gercektende cok faydali, hem hex, hem binary hemde normal sayilarin hesaplanmasinda.
DOS ve Windows
Ilk programlamaya basliyanlar icin kusursuz bir ögrenim ortami olusturan DOS ayni zamanda bazi isleri gercektende zorlastiriyor. Mesela dosda sayilari ekrana yazmak icin ASCII formatina cevirmeniz gerekiyor ki, bu bir sayinin her basamaginin tek tek cevrilmesi anlamina geliyor. DOS icat edildigi siralarda 8086 bulundugundan dolayi sadece 1MB lik adresleme kapastesine sahip DOS, ve bu DOS un en son sürümü 6.0 ile bile bugün öyle. Bunun disinda Windows 3.x de 16-Bitlik bir isletim sistemi ama 16MB lik adresleme destegi var. Yani Windows 3.x de adresler 8286 ya göre hesaplaniyorlar:
DOS(8086)
adreslemesi=16*Segment+Offset
Windows 3x(8286)
adreslemesi=256*Segment+Offset
Bunun disinda Windows 3.x su anki Windows versiyonlarina göre cok daha farkli bir coklu-kanal programlama teknigi kullaniyor. Buna göre sadece o an secili olan program calisiyor, diger kanallar arkada beklemede kaliyorlar. TSS 16-Bitlik ve cok kanalli programlama mantigi cok basit bir sekilde calisiyor Windows 3.x de. Buna göre TSS 44 Bytes büyüklügünde. Windows 95 ile gelen coklu kanal sisteminde ise her program belli bir aralikla calistiriliyor. Kanallar degistirilirken(Yani sira diger programa geldiginde) TSS(Task Switch Segment) ye programin her registeri ve Flaglari yüklüyor. 32-Bit TSS 104 Bytes büyüklügünde. Windows EDI, ESI, EBX ve EBP registerlerini kullaniyor ve bu degerleri degistirmemenizi bekliyor. Bu yüzden bu registerler kullanilmadan önce yedeklemeniz gerekiyor, aksi halde sistemi cöktürebilirsiniz. Hernekadar 8386 da 4GB gibi bir bellek alani gösterilebilsede, Windows altinda bu sadece 2GB büyüklügünde. Geri kalan 2GB Windows tarafindan ayrilmis, ve kullanimi yasak olarak duruyor. Coklu kanallilik olunca her programin adresleme kismida Windows a yükleniyor. Yani programlarin biribirlerinin degiskenlerini göstermemeleri, vs. Kisimlarida Windows hallediyor. Windows XP ise gercek bir 32-Bit isletim sistemi olma özelligi ile geliyor. Bundan önceki Windows serisi Dos üzerinde aciliyordu, ve daha sonra 32-Bit moda geciyorlardi. Bu yüzden aslinda Windows 9x serisininde 16/32-Bit bir isletim sistemi oldugu söylenebilir. 32-Bit Moda sizde programlariniz icinde DOS dan gecebilirsiniz, bunun icin programiniza su kücük satiri eklemeniz yeterli:
push cr0
; Daha sonra Real-Mode geri dönmek icin.
smsw ax
or ax,0x01 ; Protected –Mode
lmsw ax
; ...
pop cr0
; Geri Real-Mode dayiz simdik

Her ne kadar bir programin icinde Mode degistirmek fazla gerekli bir durum olmasada, burda kisa bir aciklamada bulunayim dedim. SMSW ile CR0 registerinin ilk 16-Bit tini ax e kaydedip, 1 inci biti degistererek Protected mode girmek icin gerekli degeri ax e yüklüyoruz. Daha sonrada LMSW ile ax i CR0 registerine yazarak Protected Mode geciyoruz.
Protected Mode: Windows 9x ve yeni sürümlerinin kullandigi, isletim sistemi Mode u. Bu mod un özelligi degisik programlarin birbirilerine zarar vermelerini engelleyebilmesi. Real- Mode: 8086 ile beraber gelen isletim sistemi Mode u. Pogramlamayi ögrenmek icin kusursuz bir ortam bence. Virtual 8086 Mode: Protected Mode altinda baslatilan fakat 8086 icin yazilmis programlarin calistiklari Mode.

CPUID

Pentium ile birlikte, programinizin üstünde calistigi islemci hakkinda bilgi alabilecegi bir komut geldi, CPUID. CPUID eax registerinin icinde bir fonksiyon numarasi bekler, böylelikle hangi bilgileri göndermesi gerektigini anlar. Bu bilgiler EDX icinde geri dönerler. Daha sonra TEST komutu ile geri dönen bilgilerde istenilen özelligin olup olmadigi anlasilabilir.
Mesela:
mov eax, 0x01
cpuid eax
test edx, 0x0800000
;(23 uncu bit dolu ise MMX vardir.) jnz mmx_var



EKLER
ADC
----------------------------------------
add with carry
ADC O1, O2

ADC iki elemani(O1 ve O2) toplar ve bu sonuca Carry Flags sida ekler.

Örnek:
stc
mov al, 3
mov ah, 2
adc al, ah ; al= ah+al+cf=6

ADD
--------------------------------------
ADD O1, O2
ADD O1 ile O2 yi toplayip O1 in icine yazar.
Tip:
Eger bir registere 1 eklemek
istiyorsaniz INC i kullanin.
DIV
----------------------------------------
division
DIV O1
Bu komut bölme icindir. Eger O1 8 Bit ise AX deki sayi bölünür, kalan AH nin icine ve sonuc AL nin icine yazilir.

Eger O1 16 Bit ise DX:AX icindeki sayi bölünür, kalan DX in icne sonuc AX in icine yazilir. Eger O1 32- Bit ise EDX:EAX deki sayi bölünür, kalan EDX e sonuc EAX e yazilir.
Tip:
Eger bir sayiyi 2 nin katlarina bölmek istiyorsaniz;
SHR komutunu kullanabilirsiniz.
mov ax, 24
mov bl, 8
div bl
yerine;
mov ax, 24
shr ax, 3 (2 üstü 3)
yazarsaniz kodun boyu ve hizi degisecektir.

IDIV
---------------------------------------
interger division
IDIV O1
Bo komut DIV ile hemen hemen aynidir, fark olarak isaretli sayilarlada islem yapabilir.
IMUL
---------------------------------------
interger multiply
IMUL O1, [O2, [O3]]
IMUL iki virgüllü sayiyi carpar.
Ilk olarak eger iki tane adress yada register le kullanirsaniz;
Örnek:
IMUL ax, dx
sonuc ax= ax*dx
Eger ama 3 tane adress yada register kullanirsaniz; Örnek: IMUL ax, dx, cx O zaman ax= dx*cx seklindedir.

MUL
---------------------------------------
multiply
MUL O1
MUL O1 i Akkumulator(AH, AL, AX, EAX) ile carpar.
Tip:
Eger bir sayiyi 2 nin katlariyla carpacaksaniz:
mov al, 5
mov bl, 4
mul bl
yerine;
mov al, 5
shl al, 2
seklinde yazarsaniz programinizin boyutunu ve hizini degistirmis olursunuz.

SBB
---------------------------------------
subtraction with borrow SBB O1, O2 SBB O2 ile Carry- Flag i toplayip sonuctan O1 i cikarir.

SUB
---------------------------------------
subtract
SUB O1, O2
O2 yi O1 den cikarir ve sonucu O1 e yazar.
Tip:
Bir sayidan 1 cikarmak istiyorsaniz,
Örnek:
sub ax, 1
yerine:
dec ax
yazmaniz kodunuzun boyunu ve hizini degisterecektir.

XADD
---------------------------------------
exchange and add
XADD O1, O2
XADD iki elemanin önce iceriklerini degistirir sonrada ADD komutunun yaptigini yapar.
Örnek:
mov al, 3
mob bl, 5
xadd al, bl ; Al= 8, Bl=3

KARSILASTIRMA KOMUTLARI

CMP
Compare
CMP birinci ile ikinci girilen degerleri karsilastirir ve sonucu FLAG lara yazar.
Örnek:
mov ax, 2
cmp ax, 2 ; ZF=1
CMPXCHG
Compare and exchange
Cmpxchg komutu kendisine gelen ilk degeri al, ax veya eax ile(Kendisine gelen ilk degeri boyutuna göre) karsilastirir. Eger degerler esitseler kendisine gelen ilk degere ikinci degeri yükler ve ZF ki doldurur. Örnek:
mov eax, 3
mov edx, 3
lea ecx, [eax+edx*8]
cmpxchg edx, ecx ; edx= ecx
Bunun disinda cmpxchg8b ile 64-Bit lik sayilar üstündede bu islemi yapabilirsiniz. Yalniz cmpxchg8b biraz daha degisik calisiyor, sadece bir tane adres gelmesini bekliyor kendisine, daha sonrada bu adresteki degeri EDX:EAX icindeki deger ile karsilastiriyor. Eger esitlerse ECX:EBX icindeki degeri bu adrese yaziyor.
Örnek:
Cmpxchg8b qword ptr[ebp]
TEST
Test
Test kendisine gelen degeri, ile kendisine gelen ikinci deger arasinda bir “and” islemi yapar. Ama sonucu and komuttundaki gibi kaydetmek yerine sadece FLAG lari degistirir.
FONKSIYON KOMUTLARI:

CALL
Call bir fonksiyonu cagirmak icin kullanilir. Eger bir near-call yapilirsa sadece o anki programin eip(ip) registeri yedeklenir, böylece fonksiyon bittikten sonra programda kalinan yerden devam edilebilir. Eger bir far call yapilirsa hem cs hemde eip(ip) yedeklenir.
INT
Interrupt
Int kendisine gelen 8-Bitlik(0 ile 255 arasinda sayilar) adresdeki aliciyi cagirir.
Örnek:
int 0x21 ; Dos interrupt unu cagirma.
Bunun disinda birde into vardir. Bu komut ise eger OF=1 ise bir int islemi gerceklestirir. Ama bir deger göndermeniz gerekmemektedir, otomatik olarak interrupt 0x04 ü cagirir.
RET
Ret Call ile cagrilan bir fonksiyondan tekrar dönmek icin kullanilir. Eger bir near call yapilmissa eip yi tekrar eski haline getirir. Eger bir far call yapilmissa hem cs yi hemde eip yi eski haline getirir.

MANTIKSAL OPERATORLER

Assembler
C/C++/Java

And
&&

Not !

Or
||

Xor
^

Shl
<<

Shr
>>
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:19   #19
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

REGISTER KOMUTLARI

BSWAP
---------------------------------------
byte swap
BSWAP O1
BSWAP O1 yerinde 32 Bit lik bir register bekler. 0 .ile 4. üncü byte'i ve 2. ile 3. yü degistirir. Örnek:
mov eax, 11223344h
BSWAP EAX ; EAX= 44332211h

CBW
---------------------------------------
convert byte to word CBW AL- registeri icinde bulunan seyi, bir Word seklinde AX e yazar.

CDQ
---------------------------------------
convert word to quadword CDQ EAX icindeki doubleword 'u EDX:EAX icine quadword olarak yazar.

CWD
---------------------------------------
convert word to doubleword CWD AX icinde bulunan word' u DX:AX e doubleword olarak yazar.

CWDE
---------------------------------------
convert word to doubleword extended CWDE AX icindeki word'u EAX 'E doubleword olarak yazar.
LEA
---------------------------------------
load effective address
LEA O1, O2
LEA O2 nin adresini O1 e yazar. O1 16 yada 32 Bit lik bir register olabilir. Örnek:
lea dx, deger
mov dx, offset deger
; Bu ikisi ayni isi yapar
LMSW
---------------------------------------
load machine status word
LMSW O1
O1 e CR0 registerinin ilk 16 bitini yazar(32 Protected Mode gecmeye yariyon kisimda ordadir) Ne yazikki real mode da bu gecirli degil, o yüzden mov O1, cr0 yazmaniz gerekebilir.
Bu komut aslinda isletim sistemi icindir, ve normal bir programda kullanilmasi gerekli degildir.

MOV
---------------------------------------
move
MOV O1, O2
Assembler dilinin en önemli komutudur. O1 e O2 yi tasir, önemli olan her iki Ox nun esit olmasidir. Ikinci kural ise ikisininde Segmentregister olmamasidir. 16 bitlik bir registeri 32 bit lik bir registerin icine kopyaladiginiz zaman Pentium Pro dan itibaren 0 ile diger bitler doldurulur. Önceki islemcilerde karisik bitlerle dolduruluyorlardi. Tip: xor ax, ax ; mov ax, 0 push ds ; mov ax, ds pop es ; mov es, ax

MOVSX
---------------------------------------
move with sign- extension MOVSX O1, O2 MOVSX o1 in icine o2 yi kopyalar, burdaki fark ise o1 in 16 yada 32 bit olup o2 nin 8 veya 16 bit olabilmesidir. Örnek: mov ax, 0 mov bl, -5 movsx ax, bl

MOVZX
---------------------------------------
move with zero- extend
MOVZX O1, O2

POP
---------------------------------------
POP O1
Stak(daha önce PUSH lanmis seyler) tan O1 icine cekmeye yarar. Stak n son karakterini ceker. Eger O1 16-Bit ise SP = SP+ 2 eger O1 32-Bit ise SP= SP+4 olur.

POPA
---------------------------------------
pop all
POPA bütün registerleri kullanmak icindir. Registerler siradaki gibi kullanilmis olurlar;
DI, SI, BP, BX, DX, CX, AX
POPAD
-------------------------------------
pop all doubleword
Baknz: POPA

POPAW
-------------------------------------
pop all word
Baknz: POPA

PUSH
--------------------------------------
PUSH O1
Stak 'a eleman göndermeye yarar, ama o1 8- Bitlik bir eleman olamaz. Eger O1 16-Bit ise SP = SP- 2 eger O1 32-Bit ise SP= SP- 4 olur.

PUSHA
--------------------------------------
push all
16 bitlik bütün registerleri su sirada pushlar;
AX, CX, DX, BX, SP, BP, SI, DI.

PUSHAD
------------------------------------
push all doubleword
baknz: PUSA

PUSHAW
--------------------------------------
push all word
baknz: PUSHA

SMSW ---------------------------------------
store machine status word
SMSW O1
SMSW CR0 in ilk 16 bitini O1 e kaydeder. Aslinda isletim sisteminin ihtiyac duydugu, bir komuttur ve bir uygulamada kullanilmasi gerekli degildir.

MSRs
-------------------------------------- 80 nin üzerinde MSR vardir, ama her islemcide degisik olabilirler. Bu yüzden Pogramlamada fazla kullanilmamaktadirlar, WRMSR ile EDX: EAX icindeki eleman yazilir, RDMSR ile okunurlar. Tip: Hayla merak ediyorsaniz Döküman Nr. 245472 de Pentium4 ün MSRs hakkinda bilgi bulabilirsiniz, developer.intel.com da.

XCHG --------------------------------------
exchange
XCHG O1, O2
Iki elemanin iceriklerini degistirir. XLAT
---------------------------------------
translate
XLAT [O1]
XLAT DShttp://www.supermp3.org/images/smilies/frown.gifE)BX adresindeki degeri AL ye kopyalar. Önceden AL de hangi Byte istendigi yazilmalidir.
Örnek:
var db "ABCDE"
...
lea bx, var
mov al, 3 ;Dördüncü eleman
XLAT ; AL=D
...
XLAT ES: O1

EK B: NASILSINIZ?

; 2003 Anil Öner
.model small
.data

msg db "Iyimisiniz?([E]vet/[H]ayir)$"
msg2 db 0Ah, "Iyi. http://www.supermp3.org/images/smilies/smile.gif$"
msg3 db 0Ah, "Kotu. http://www.supermp3.org/images/smilies/frown.gif$"
.code
start:
mov ax, @data ; ds = data
mov ds, ax
mov ah, 09h
lea dx, msg ; Ekrana msg yi yaz.
int 21h
mov ah, 07h
int 21h
cmp al, 'e'
je sec_1
cmp al, 'E'
je sec_1 ; e yada E ise sec_1 e git.
mov ah, 09h
lea dx, msg3 ; degilse msg3 u ekrana yaz
int 21h
sec_1: ; iyi ise
mov ah, 09h
lea dx, msg2
int 21h
son:
mov ah, 04ch ; cikis
int 21h
end start
ends

EK C: AMD vs Intel(I64 vs X86-64)


Bu yazimda size bir kac yeni teknolojiden söz edecegim. Eminim ki aranizda Ia64 ve x86-64 ü duymus olanlar vardir.
Bu iki teknolojide 64- Bitlik sistemler.
Ia64
----------------------------------------------------------------------------
Intelin CISC tabanli islemcileriyle Hp nin RISC tabanli islemcilerinin komutlarinin birlestirilmesiyle olusmus EPIC teknolojisine dayaniyor. Ilk EPIC islemci Itanium' du. Itanium Server ler icin gelistirilmis bir islemciydi, bu yüzden pahali. IA64 gercekten cok fazla registere sahip. Bu yüzden ziplama orani düsürülebiliyor. Buda gercekten cok iyi bir performans demek oluyor. Tabiki EPIC in gercek ten zor oldugunu söylemem gerek. Bunun disinda derleyicilerde EPIC icin cok optimize edilmis kod yaratamiyorlar.
Iste örnek bir kod:
Mantik
Eger p1=p2
r2=r3+r4
Yoksa
r7=r6-r5
EPIC:
cmp.eq p1, p2 = r1, r0
(p2) br.cond else_clause
add r2 = r3, r4
br.endif
else_clause:
sub r7 = r6, r5
endif:
....

Tabiki yukaridaki kod daha optimize edilmeden x86 gözüyle bakilarak yazildi, yani ziplama komutlariyla. Ayni Kodun optimize edilmis hali:
EPIC:
cmp.eq p1, p2 = r1, r0
(p1) add r2 = r3, r4
(p2) sub r7 = r6, r5
...
x86-64
Constantin Ofline   Alıntı ile Cevapla
Alt 06-09-2008, 15:19   #20
ยŦยк
 
Constantin - ait Kullanıcı Resmi (Avatar)
 

Simdide x86-64 sistemine bakalim. Ia64 ün aksine x86-64 Ia32 programlarini da 64- Bitlik programlarla ayni hizda calistirabiliyor. Eski x86 komut satirini kullaniyor, ama tabiki bircok yeni gelismeyle, bulardan en önemlileri:
-Eski registerlerin 64- Bitlik leri ve 8 yeni 64- Bit register.
-Daha temiz ve kullanisli bir FPU
-Gercek 64 Bitli adresleme
x86-64 de Intelin 16- Bit den 32- Bit e gecerken yaptigi straji kullaniliyor. Ilk x86-64 islemci AMD denin Hammer adli islemcisi.
Gcc de derlenmis örnek bir kod su sekilde gözüküyor:
Hammer: gcc
-------------------------------------------------------------------------------
C:
int bar(int a,int b,int c) { return foo(a,b,c,0); }
bar_x86: bar_hammer:
pushl %ebp xorl %ecx, %ecx
movl %esp, %ebp jmp foo
pushl $0
pushl 16(%ebp)
pushl 12(%ebp)
pushl 8(%ebp)
call foo
addl $16, %esp
leave
ret
...

Ve Gelecek
----------------------------------------------------------------------------
Peki ya gelecek, acaba Intel IA64 üylemi yeni nesil islemci modelini belirleyecek, yada AMD x86-64 üylemi.
Nasil olursa olsun 64- Bit lik islemcilerin kapida oldugunu görmemek olagan degil. Intel Serverler icin 64- Bitlik islemci yaratmaya calisirken, AMD Desktop Pc ler icin bunun aynisi yapmaya calisiyor. Peki ya gercektende Desktop Pclerin buna ihtiyaclari varmi? Gercektende gelecekte 16TByte lik Ram lar kullanmamiz gerekecekmi? Iste bu tip sorularin cevabini vu yilin sonuna dogru Amd nin Hammer islemcisi cikinca alacagimizi düsünüyorum. Eger AMD Hammer tutarsa büyük ihtimalle Intel 32- Bitlik Pentium 5 in tasarimini 64- Bitlik EPIC tasarimiyla zenginlestirip, masaüstüne sunmaya calisacaktir. Ama su anda x86-64 daha parlak bir gelecege sahip benziyor, cünkü 32Bitlik programlar cok fazla. Ve Intelin EPIC seti 32 Bitlik islemcileri gercekten yavas calistiriyor.
Yani su birkac yil bilgisayarlar icin cok önemli,
Iyi calismalar...
Kaynaklar:
-----------------------------------
Welcome to Intel (Welcome to Intel)
Advanced Micro Devices, AMD ? Global Provider of Innovative Microprocessor, Graphics and Media Solutions (Advanced Micro Devices, AMD ? Global Provider of Innovative Microprocessor, Graphics and Media Solutions)
AMD Athon 64
IA64 Assembler
IA64 vs X86-64 was soll ein Hacker darüber wissen?
Itanium Sowftware Developer's Manual Volume 1,2,3


EK C: Küyük bir isletim sistemi YAZMAK!


Hangi Dil?
----------------------------------------------------------------------------
Isletim sistemini aslinda C/C++ da yapmak isterim, ama mesela ekrana girdi vermek istedigimde bunun icin gerekli olan "printf" komutunu cagirmam gerektigini varsayalim. O zaman adindaki baslik dosyasini kullanmam gerekmekte.Ama sorun her basligin C/C++ derliyicileri tarafindan belli isletim sistemler(yada belli sistemler) icin tasarlandigi icin ne yazikki C/C++ dillerini cekirdegi yazarken kullanmayacagim fakat sonradan isletim sisteminin devamini C/C++ ile yazabilirsiniz.
Söyle düsük seviyede Assembler bilginiz olmasi sizin cekirdegi daha iyi anlamanizi saglayacaktir...
Gerekenler
---------------------------------------------------------------------------
1.Netwide Assembler (NASM)
2.RaWrite yada Diskete Imageleri yazacak baska bir program.
3.Bos bir disket.
Buraya Dikkat!
----------------------------------------------------------------------------
Size söylemem gerekirki Assembler ile cok sey yapilabilir(yada cok sey yanlis yapilabilir).Bu bilgisayariniza gelebilecek herhangibir zarar benim degil, sizin sucunuzdur!
Basliyoruz
----------------------------------------------------------------------------
Bir isletim sisteminin nasil calistigini anlamak icin, önce bir bilgisayarin nasil calistigini iyi anlamak gerekir. Burada kisaca söylüyorum ki, önce bilgisayar acilir, hemen BIOS devreye girer ve denetimler yaptiktan sonra isletim sistemini cagirir. BIOS hangi sürücünün önce "BOOT" lanacagini belirler. Isletim sistemini önce yerel sürücüde arar. Biz isletim sistemimizi diskete yazacagiz.
Simdik kodlari yazmaya basliyalim;
----------------------------------------------------------------------------
Ilk Kernel:
Tabiki bir Kernel sadece bir mesaj ekrana yazip sistemi yeniden baslatmak la kalmaz ama böyle bir kod yapiyi anlamak icin kolaydir:
--------------------------------------------------------
mov ax, 1000h
mov ds, ax
mov es, ax
start: ; Burda gercek anlamda isletim
; sistemimize basliyoruz.
mov si, msg ; hemen bir string gösteriyoruz
call put
call read ; "oku" bir tusa basilana kadar bekler
jmp reset
msg db "Yeniden baslatmak icin bir tusa"
db "basin!",13,10,0
put:
lodsb
or al, al
jz short put_d
mov ah, 0x0E
mov bx, 0x0007
int 0x10
jmp put

put_d:
retn

read:
mov ah, 0
int 016h
ret

reset:
db 0Eah
dw 0000h
dw 0FFFFh
---------------------------------------------------------
Dosyayi kernel.asm diye kaydettikten sonra;
nasm –f bin –o kernel.bin kernel.asm
seklinde derlenmelidir.

Bir BOOTMANAGER
----------------------------------------------------------------------------

BIOS ilk acildiginda 512Bytes boyutunda bir OP-Code arar ve BIOS bu dosyayi 0x7C00 adresine yükler.
-----------------------BOOT.ASM--------------------------
org 0x7C00 ; Öncelikle dosyanin adresini ayaliyoruz.

start:
cli ; Interrupts kullanma!
mov ax, 0x9000 ; Stack adresini kayit etme
mov ss, ax
mov sp, 0 ; Stackpointer' 0 lamak
sti

mov [bootdriv], dl
call load ; Kernel i yükleme

mov ax, 0x1000 ; 0x1000 Shell' in adresi
mov es, ax
mov ds, ax
push ax
mov ax, 0
push ax
retf

bootdriv db 0
loadmsg db "Sistem Yükleniyor...",13,10,0

putstr:
lodsb
or al,al
jz short putstrd
mov ah,0x0E
mov bx,0x0007
int 0x10
jmp putstr
putstrd:
retn

load:
push ds
mov ax, 0
mov dl, [bootdriv]
int 13h
pop ds
jc load

load1:
mov ax,0x1000
mov es,ax
mov bx, 0
mov ah, 2
mov al, 5
mov cx, 2
mov dx, 0
int 13h
jc load1
mov si,loadmsg
call putstr
retn

;Programin 512 Bytes dan büyük olmamasi icin...
times 512-($-$$)-2 db 0
dw 0AA55h ; Bu da BIOS sa bitis talimatini verir
----------------------------------------------------
nasm –f bin –o boot.bin boot.asm seklinde de dosya derlenmelidir.

Simdide isletim sistemimizi Diskete yükleyip calistirmak icin;

copy boot.bin+kernel.bin vitaxia.img
Seklinde iki dosyayi birlestiriyoruz.
Son olarak da RaWrite programi ile bu img dosyasini diske yaziyoruz. Disketi sokup bilgisayari yeniden baslattigimizda isletim sistemimiz calisacaktir.
Son olarak tabi ki bunu hepsi sadece bir örnek, nasil bir isletim sistemi yapabilecegimize dahil.
Constantin Ofline   Alıntı ile Cevapla
Cevapla

Bu konuyu arkadaşlarınızla paylaşın


Konuyu Toplam 1 Üye okuyor. (0 Kayıtlı üye ve 1 Misafir)
 

Yetkileriniz
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is Açık
Smileler Açık
[IMG] Kodları Açık
HTML-KodlarıKapalı
Trackbacks are Açık
Pingbacks are Açık
Refbacks are Açık




Türkiye`de Saat: 08:47 .

Powered by vBulletin® Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.3.2

Sitemiz CSS Standartlarına uygundur. Sitemiz XHTML Standartlarına uygundur

Oracle DBA | Kadife | Oracle Danışmanlık



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580