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