-
Notifications
You must be signed in to change notification settings - Fork 0
/
factorial.asm
187 lines (153 loc) · 4.94 KB
/
factorial.asm
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
;-----------------------------
; Klavyeden girilen (en fazla 2 basamaklı) sayı,
; girildikten sonra ENTER tuşuna basıldığında faktöriyelini hesaplayan
; ve sonucunu ekrana ve dosyaya yazan assembly program kodu.
;----------------------------------------------------------------------
org 100h
jmp basla
;---------------------
; Değişkenler/Diziler
;---------------------
sonuc db 160 dup(0) ; en büyük sonuç (99 faktöriyel), maksimum 156 karakter olacaktır.
girilen dw 0
sayiGirMsg db 0dh,0ah,"Faktoriyeli alinacak sayiyi girin: $"
sonucMsg db 0dh,0ah,0dh,0ah,"Girilen sayinin faktoriyeli: $"
dosyaMsg db 0dh,0ah,0dh,0ah,"Cikan sonuc, ...\vdrive\C\odevSonuc.txt dizinine yazdirildi!$"
dosya db "C:\odevSonuc.txt",0
dosyaHandle dw ?
dosyaBuffer db 160 dup(' ')
dosyaSize dw 0
basla:
lea si,sonuc
mov byte ptr [si],01h
call sayiGirMesaji
call girilenSayiyiBelirle
mov dl,al
cmp dl,0 ; girilen sayı 0 ise.
jne devam
mov dl,01h ; 0! = 1
mov al,dl
devam:
cmp dl,25 ; 25!'e kadar, hesaplamadan çıkan sonucun basamak sayısı, girilen sayıdan düşük oluyor.
jb yirmiBesAsagi ; 25! sonrası, hesaplamadan çıkan sonucun basamak sayısı, girilen sayıdan büyük oluyor.
jmp yirmiBesveYukari ; maksimum 99!'in sonucu, 156 basamaklı bir sayı oluyor.
yirmiBesAsagi:
mov girilen,ax ; 25!'in altındaki hesaplamalar için, girilen sayının kendisini verebiliriz.
jmp faktoriyel ; Böylece 25! altındaki hesaplamalar için daha az zaman harcamış oluyoruz.
yirmiBesveYukari:
mov girilen,ax
add girilen,60
faktoriyel:
push dx
call hesapla
pop dx
dec dl
jnz faktoriyel
call ekranaYazdir
call dosyayaYazdir
hlt
;-------------
; Prosedürler
;-------------
sayiGirMesaji proc
mov dx,offset sayiGirMsg
mov ah,09h
int 21h
ret
sayiGirMesaji endp
girilenSayiyiBelirle proc
mov bx,0000h
mov dx,0000h
mov cx,000Ah
yeniKarakterGirisi:
push bx ; bx, girilmiş karakterler ile oluşturulan esas sayıdır.
mov ah,01h ; burada klavyeden girilen karakter okunur.
int 21h ; al=girilen karakter
mov ah,00h
pop bx ; önceki bx, diğer işlemlerden etkilenmesin diye stack belleğe atılır.
cmp al,0dh ; girilen karakterin, enter olup olmadığına bakılır.
jz tamamdir ; enter ise karakter girme işlemi tamamlanmıştır.
sub al,30h ; enter değilse, girilen ascii karakter, sayısal değere çevrilir.
push ax ; önceki sayı 10 ile çarpılır ve bir sayı elde edilir, sonraki karakter o sayıya eklenir.
mov ax,bx
mul cx
mov bx,ax
pop ax
add bx,ax
jmp yeniKarakterGirisi
tamamdir:
mov ax,bx ; girilen esas sayı bx'ten ax'e aktarılır.
ret
girilenSayiyiBelirle endp
hesapla proc
cmp dl,01h
jz sonucBir
lea si,sonuc
mov dh,10
mov bx,0000h
mov cx,girilen
donDolasYineGel:
mov al,[si]
mov ah,00h
mul dl
add ax,bx
div dh ; çıkan sonucu sürekli 10'a bölerek, her bir basamak değerini elde ediyoruz.
mov [si],ah ; her bir basamak değerini, sonuc dizimize birer eleman olarak ekliyoruz.
inc si
mov bl,al
loop donDolasYineGel
sonucBir:
ret
hesapla endp
ekranaYazdir proc
mov dx,offset sonucMsg
mov ah,09h
int 21h
mov bp,0 ; hesaplamanın sonucu, basamak basamak sonuc dizisinde ters olarak kayıtlıdır.
lea si,sonuc ; sonuc dizisini tersten okuyup, karakter karakter sonucu ekrana yazdırıyoruz.
mov di,si
mov cx,girilen
add di,cx
dec di
zekiCIPLAK:
cmp byte ptr [di],00h
jne zkcplk
dec di
jmp zekiCIPLAK
zkcplk:
mov ah,02h
yaz:
mov dl,[di]
add dl,30h
mov dosyaBuffer[bp],dl ; dosyaya yazarken kullanmak için dosyaBuffer dizisini dolduruyoruz.
inc bp
int 21h
cmp si,di
je bitis
dec di
loop yaz
bitis:
mov dosyaSize,bp
ret
ekranaYazdir endp
dosyayaYazdir proc
mov ah,3Ch ; yazılacak dosyayı oluşturuyoruz.
mov cx,0000h
mov dx,offset dosya
mov ah,3Ch
int 21h
mov dosyaHandle,ax ; dosyaHandle ile artık dosyaya her türlü işlemi yaptırabiliriz.
mov ah,40h ; dosyaya yazma işlemi
mov bx,dosyaHandle
lea dx,dosyaBuffer
mov cx,dosyaSize
int 21h ; C:\emu8086\vdrive\C dizininde odevSonuc.txt dosyasına yazılacaktır.
mov ah,3eh ; burada dosyayı kapatıyoruz.
mov bx,dosyaHandle
int 21h
mov dx,offset dosyaMsg ; dosyanın başarıyla yazıldığını ekranda bildiriyoruz.
mov ah,09h
int 21h
ret
dosyayaYazdir endp
; Zeki ÇIPLAK