07 Ocak
2010
21:46

Mikro İşlemciler Projesi

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. :D )

Kodları emu8086 emulatörünün dördüncü sürümünde sorunsuzca çalıştırabilirsiniz.

Gelgelim proje metnine ve çözümlerime…

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.

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
; UMUT BENZER
; 05-06-7670
; http://www.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.

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
; Umut Benzer
; 05-06-7670
; http://www.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.

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
; Umut Benzer
; 05-06-7670
; http://www.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.

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
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

toplam 771 kez okundu | bugün okuyan olmadı

4 yorum var.

  1. 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 08 Ocak 2010
  2. “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.

    Canburak 08 Ocak 2010
  3. @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)

    Umut 08 Ocak 2010
  4. @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.

    Canburak 08 Ocak 2010

Eklemek istedikleriniz?