Ege Üniversitesi Bilgisayar Mühendisliği 3. Sınıflar için 4 Ocak 2010 Pazartesi gününe verilen mikro ödevi için benim çözümlerimi yazıda bulabilirsiniz.
Projeyi yapmanın zor geldiğini söylemeliyim en başta. Oturup C yazar gibi ASM yazmak olacak iş değilmiş onu fark ettim. Baktım, adım atamıyorum, proje bana bakıyor, ben projeye, dedim bu iş böyle olmayacak.
Açtım boş bir sayfa, C’ye benzer ama C olmayan, benim “tarzanca” olarak adlandırdığım bir dil ile kodları önce anlayabileceğim şekilde yazdım. For’lu if’li şekillerde, değişken kullanarak. Sonra ikinci defa kodların üstünden geçerek, bunları ASM’ye “derledim”.
Böyle yapınca, kendimi daha üst seviyeli bir dilde yazıyor gibi hissettim kodları. Projeye etkinlikten puan verilmeyecek olması da bu isteğimi gerçekleştirmemi sağladı. (Dördüncü ödev ne kadar sonsuz döngüye giriyormuş gibi dursa da, emu8086’da çalıştırırsanız 15 dakika sonra program bitiyor, doğru da çözüyor. 😀 )
Kodları emu8086 emulatörünün dördüncü sürümünde sorunsuzca çalıştırabilirsiniz.
Gelgelim proje metnine ve çözümlerime…
- Proje Metni
- Benim Çözümlerim (4 ASM dosyası, sıkıştırılmış)
Eğer kodları indirmeden incelemek isterseniz yazının devamına bakabilirsiniz.
Ödev 1: Palindromlar
Projenin ilk kısmında başlangıç adresi SI’da olan, data segmentteki bir metnin içindeki kelimelerin kaç tanesinin palindrom olduğunun sayısı isteniyordu. Benim kodumda bu sayı CX registerından alınabilir.
DİKKAT: Palindrom ASM’si bazen hatalı sonuçlar göndermekte olup, çalışmak için kullanılmaması şiddetle önerilir. Hatayı yakalayan olup da bana haber verirse çok mutlu olurum.
; UMUT BENZER ; 05-06-7670 ; https://ubenzer.com/ ; SURUM 2 data segment character dw ? ; En son islenen karakterin pointerini tutar palindrom dw 0 ; Kac tane palindrom kelime bulundugunu tutar simdiki_cumlenin_karakter_sayisi dw 0 ; Process edilen kelimede kac harf oldugunu tutar. curr_palindrom db 0 ; Process edilen kelime palindromsa 0, degilse 1 cumle_baslangici dw ? ; Process edilen kelimenin baslangic pointeri karsilastirilacak dw ? ; Process edilen kelimede karsilastirilacak harf sayisi son_kelime_mi db 0 cumle db ' . A A. AA ABA ABBA ADA ADDA A A REM UMUT BENZER SCORPIONS BILMUH DENEME.DENEME DENEME DENEEEEME PALINDROM 123 121 DENEME ASA A $ DOLARDAN $ SONRA ABBA REM SCORPIONS VS.' ends code segment start: MOV ax, data MOV ds, ax MOV es, ax MOV SI, OFFSET cumle MOV character, OFFSET SI enbas: MOV simdiki_cumlenin_karakter_sayisi, 0 MOV curr_palindrom, 0 MOV AX, character MOV cumle_baslangici, AX karakter_sayma_basladi: MOV BX, character MOV AX, SI[BX] SUB AL, '$' JZ son_kelime MOV AX, SI[BX] SUB AL, ' ' JZ karakter_sayma_bitti MOV AX, SI[BX] SUB AL, '.' JZ karakter_sayma_bitti INC simdiki_cumlenin_karakter_sayisi INC character; JMP karakter_sayma_basladi son_kelime: MOV son_kelime_mi, 1 MOV curr_palindrom, 1 karakter_sayma_bitti: MOV DX,0 MOV AX,simdiki_cumlenin_karakter_sayisi CMP AX,1 JNZ bir_karakter_degil INC palindrom INC character JMP karakter_sarma_basladi bir_karakter_degil: CMP AX,0 JNZ sifir_karakter_degil INC character; JMP karakter_sarma_basladi sifir_karakter_degil: MOV BX, 2 DIV BX MOV karsilastirilacak, AX ; for MOV CX, 0 palindrom_mu_dongusu: MOV BX, karsilastirilacak SUB BX,CX JZ palindrom_mu_dongusu_bitti ; if MOV BX, cumle_baslangici ADD BX, CX MOV AX, SI[BX] MOV BX, cumle_baslangici ADD BX, simdiki_cumlenin_karakter_sayisi SUB BX, 1 ; Ilk eleman 0.indis ile basladigi icin SUB BX, CX MOV DX, SI[BX] SUB AL, DL JZ palindrom_mu_dongusu_sonu MOV curr_palindrom, 1 MOV CX,karsilastirilacak DEC CX ;end if palindrom_mu_dongusu_sonu: INC CX JMP palindrom_mu_dongusu: palindrom_mu_dongusu_bitti: ; endfor MOV AL, curr_palindrom SUB AL, 0 JNZ palindrom_degil INC palindrom palindrom_degil: ;bitti mi kontrol bitti_mi_kontrol: MOV BL, son_kelime_mi SUB BL, 1 JZ bitirirken ;bitmediyse bir sonraki kelimenin basina gidelim. karakter_sarma_basladi: MOV BX, character MOV AX, SI[BX] SUB AL, ' ' JZ karakter_sar MOV AX, SI[BX] SUB AL, '.' JZ karakter_sar JMP enbas karakter_sar: INC character; JMP karakter_sarma_basladi bitirirken: MOV CX, palindrom MOV ax, 4c00h ; exit to operating system. INT 21h ends end start ; set entry point and stop the assembler.
Ödev 2: EKOK
Verilen iki sayının en küçük ortak katının bulunması isteniyordu. (EKOK, LCM) Benim kodumda bu değer BX registerından alınabilir. Bu kodda prosedür çağrılması ve recursiona (öz yineleme) örnek bulunabilir.
; Umut Benzer ; 05-06-7670 ; https://ubenzer.com/ data segment sayi1 dw 200 sayi2 dw 70 ends stack segment dw 128 dup(0) ends code segment gcd proc ; PARAMETRELER AX VE BX'ten alinip, sonuc BX'te verilir. CMP BX,0 JNE bx_sifir_degil MOV BX, AX RET bx_sifir_degil: MOV CX,BX MOV DX,0 DIV BX MOV BX,DX MOV AX,CX CALL gcd RET endp start: MOV AX, data MOV DS, AX MOV ES, AX ; LCM = sayi1 * sayi2 / GCD(a,b) MOV AX, sayi1 MOV BX, sayi2 CMP AX, BX JG a_buyuk_b: ; Eger BX AX'ten buyukse yerlerini degistirelim. MOV CX,BX MOV BX,AX MOV AX,CX a_buyuk_b: PUSH AX PUSH BX CALL gcd POP AX POP CX MUL CX DIV BX MOV BX,AX MOV AX, 4c00h INT 21h ends end start
Ödev 3: Faktoriyel
Projenin üçüncü kısmında recursion kullanarak verilen bir sayının ASM’de bulunması isteniyordu. Benim ödevimde sonuç CX’ten alınabilir. Bu ödev 16 bit’ten daha büyük sonuçları doğru görüntülemez.
; Umut Benzer ; 05-06-7670 ; https://ubenzer.com/ data segment sayi dw 0 ends stack segment dw 128 dup(0) ends code segment faktoriyel proc ; 0 faktoriyel ozel durumu CMP AX, 0 JNE sifir_diil MOV BX, 1 RET ; 1 faktoriyel base durum sifir_diil: CMP AX, 1 JNE bir_diil MOV BX, 1 RET ; Diger durumlar bir_diil: PUSH AX DEC AX CALL OFFSET faktoriyel POP AX MUL BX MOV BX,AX RET endp start: MOV AX, data MOV DS, AX MOV ES, AX MOV AX, sayi MOV CX, OFFSET faktoriyel CALL CX MOV CX, BX ; Sonuc BX ve CX'tedir. ; Program 16'bitten buyuk sonuclari dogru goruntuleyemez. MOV AX, 4c00h int 21h ends end start
Ödev 4: Parity Bitleri
Bu ödevde 100 baytlık bir tablonun (sütunlar bitler, satırlar baytlar) even parity bitlerinin bulunması isteniyordu. Bu kod aşırı uzun olmasına ve çok aşırı uzun sürede çalışmasına rağmen doğru bir hesaplama yapmakta olup, hem dikey hem yatay parityleri doğru bir şekilde hesaplamaktadır. Sonuç, ilgili bellek bölgesindeki değişiklikler izlenerek görülebilir.
DİKKAT: Bu ASM etkin değildir ve çok daha kısa sürede çalışabilecek kodlar yazılabilir. Sonuç doğru olmakla beraber bu kodun dikkate alınıp üzerinde çalışılmamasını şiddetle öneririm.
data segment ;bilgiler db 100 DUP(11111111B) bilgiler db 11110111B,01011110B,01011010B,10001000B,11111010B,11111111B,00000000B,10101000B,00101111B,01111010B, 90 DUP(11111111B), ? sayi equ 100 i db ? parity db 0 ends stack segment dw 128 dup(0) ends code segment get_mask proc CMP CH,0 JNE sifir_degil MOV DL, 10000000B ;MASK sifir_degil: CMP CH,1 JNE bir_degil MOV DL, 01000000B ;MASK bir_degil: CMP CH,2 JNE iki_degil MOV DL, 00100000B ;MASK iki_degil: CMP CH,3 JNE uc_degil MOV DL, 00010000B ;MASK uc_degil: CMP CH,4 JNE dort_degil MOV DL, 00001000B ;MASK dort_degil: CMP CH,5 JNE bes_degil MOV DL, 00000100B ;MASK bes_degil: CMP CH,6 JNE alti_degil MOV DL, 00000010B ;MASK alti_degil: CMP CH,7 JNE yedi_degil MOV DL, 00000001B ;MASK yedi_degil: RET endp start: mov ax, data mov ds, ax mov es, ax ; Once ROW parity bitleri ; for baslangici MOV CL, 0 satir_gezintisi: CMP CL, sayi ; DONGU SAYISI JE satir_gezintisi_bitti MOV i,CL ; for baslangici MOV SI, OFFSET bilgiler MOV CH,0 ADD SI, CX MOV AL, DS:[SI] ; Siradaki kelimeyi getir MOV parity, 0 ; ikinci for baslangici MOV CH, 0 ic_satir_gezintisi: CMP CH,7 JE ic_satir_gezintisi_bitti ; for baslangici CALL get_mask ; Birinci karakter kontrolu AND AL,11111110B MOV BL,AL AND BL, DL ; APPLY MASK SUB BL, 0 JZ problem_yok ; Partiye gelecek olan degeri tersine cevir MOV BH,parity SUB BH,0 JNZ sifir_yap: MOV parity,1 JMP devam sifir_yap: MOV parity,0 devam: problem_yok: ; for sonu INC CH JMP ic_satir_gezintisi ic_satir_gezintisi_bitti: ; for sonu OR AL, parity MOV DS:[SI],AL ; for sonu MOV CL,i INC CL JMP satir_gezintisi satir_gezintisi_bitti: ; for sonu ; COLUMN parity bitleri MOV SI, OFFSET bilgiler MOV BX, sayi ; DONGU SAYISI ADD SI, BX MOV DS:[SI],0 ; Siradaki kelimeyi getir ; for baslangici MOV CH, 0 sutun_gezintisi: CMP CH, 8 JE sutun_gezintisi_bitti ; for baslangici MOV parity, 1 ; ikinci for baslangici MOV CL, 0 ic_sutun_gezintisi: CMP CL, sayi ; DONGU SAYISI JE ic_sutun_gezintisi_bitti MOV i,CL ; for baslangici MOV SI, OFFSET bilgiler MOV BL,CL MOV BH,0 ADD SI, BX MOV AL, DS:[SI] ; Siradaki kelimeyi getir CALL get_mask ; Birinci karakter kontrolu MOV BL, AL AND BL, DL ; APPLY MASK SUB BL, 0 JZ problem_yok_sutun ; Partiye gelecek olan degeri tersine cevir MOV BH,parity SUB BH,0 JNZ sifir_yap_sutun: MOV parity,1 JMP devam_sutun sifir_yap_sutun: MOV parity,0 devam_sutun: problem_yok_sutun: ; for sonu MOV CL,i INC CL JMP ic_sutun_gezintisi ic_sutun_gezintisi_bitti: ; for sonu CMP parity,0 JNE degisiklik_gerekli_degil MOV SI, OFFSET bilgiler MOV BX, sayi ADD SI, BX OR DS:[SI],DL degisiklik_gerekli_degil: ; for sonu INC CH JMP sutun_gezintisi sutun_gezintisi_bitti: ; for sonu MOV ax, 4C00H ; exit to operating system. int 21H ends end start ; set entry point and stop the assembler.
İyi günler
Mikro İşlemciler Projesi 6 yorum aldı.
Merhaba Umut,
C gibi yazmadan önce akış diyagramını çizmenizin faydası olacağını düşünüyorum. Gerçi bundan sonra ne zaman yazarsınız bilmem ama yine de söylemek gerek
@Okan Bursa: Merhaba Hocam, finallere hazırlanırken flowchartlar ile kod yazmayı deneyeceğim, öneriniz için çok teşekkür ederim.
@Canburak: İki sayının en küçük ortak böleninin bir olduğu konusundaki matematiksel ispatın için teşekkür ederim, ancak senin de yorumunun sonunda fark ettiğin üzere bu sadece bir yazım hatası olmuş. Yine de beni iki sayının ikisinin de en az bire bölünebileceği konusunda aydınlatlattığın için çok sağol, aklıma gelmeyebilirdi. Yazım hatasını düzeltiyorum. Tespit için tekrar tekrar teşekkürler, İtalya’ya sevgiler. (eğer doğru hatırlıyorsam)
“Verilen iki sayının en küçük ortak böleninin bulunması isteniyordu. (EBOB) ”
Böyle bir cümle kullanmışsın ancak bu cümle hatalı. EBOB -> En Büyük Ortak Bölen kavramının kısaltmasıdır en küçük değil. Zaten iki sayının en küçük ortak böleni eğer kümeyi sayma sayıları olarak alırsak 1 olur. Eğer tam sayılar kümesini düşünürsek bu durumda iki sayının EBOB unun toplama işlemine göre tersi bize en küçük ortak böleni verebilir.
Neyse işin matematik kısmını boşver. Adlandırmada hata var.
@Umut işin matematik kısmını can sıkıntısından yazmıştım. Sana bilmediğini ima etmek ya da bir şey öğretmek için değildi. Yanlış anlaşılma olduysa özür dilerim. İtalya konusunda da evet doğru hatırlıyorsun.
oshansoftta 8085 similatörüneq basic complier ile bir proje yazmam lazım yılan yada trafik ışığı bu konuda bana yardımcı olabilirmisiniz çok acil
meraba hocam emu 8086 da 16 bit lik bilgisayarda 0 dan 9 a kadar sayan sayıcı devresi 9 dan sonra tekrar başa dönüp tekrar 9 a kadar sayan bu şekılde tekrarlayan programı nasıl yazabiliriz teşekkürler şimdiden
Harici monitör parlaklığı klavye ile nasıl değiştirilir?
Ağaç Veri Yapısı [C++ Örnek]
Almanya’da nasıl ehliyet aldım?
‘de, da’ eki nasıl yazılır?
Almanya’da nasıl ehliyet aldım?
Bir şirket neden uzaktan çalışmaya (remote working) izin verir?
-de -da eki ne zaman ayrı yazılır?
Almanya’ya gelmek için yapılan bürokratik işlemler