I have tried your program and it works fine except that you seem to consider 0 and 1 prime numbers. That's not correct.
A prime number is a number bigger than 1, that is only divisible by itself and by 1.
The quick fix is below:
...
MOV AL, NUM
cmp al, 2 <<<< Add this line
jb NPRIME <<<< Add this line
MOV BL, 02H
MOV BH,00H
MOV DX,0000H
MOV AH,00H
UP:DIV BL
CMP AH,00H
JNE NEXT
INC BH
NEXT: CMP BH, 02H
JE NPRIME
INC BL
MOV AX, 0000H
MOV DX, 0000H
MOV AL, NUM
CMP BL, NUM
JBE UP
PRIME:
INC PR
JMP EXIT
NPRIME:
INC NPR
EXIT:
...
Not much of an answer if I would leave it at that! So allow me the following observations:
- Zeroing
DX
is a twice repeated, redundant operation
- You can load
BH
and BL
in one operation
- Don't load the number at two different places
- The variables PR and NPR are mutually exclusive, so a single variable would be enough
- You don't need branching in order to increment the counter
The better fix is below:
...
cmp NUM, 2
jb NPRIME ; 0 and 1 are no prime numbers
mov bx, 0002h ; BH=0 (counter), BL=2 (divisor)
UP:
mov al, NUM
mov ah, 0
div bl
cmp ah, 1 ; Only sets carry flag is remainder is 0
adc bh, 0 ; Conditional increment of counter
cmp bh, 2
je NPRIME
inc bl
cmp bl, NUM
jbe UP
PRIME:
inc PR
NPRIME:
EXIT:
...
Because your algorithm tries every divisor up to the number itself, even the above proposed changes will not make the program truly efficient.
I could add a version of the code that would be at least 10 times faster. In case you're interested, leave me a comment and perhaps I could add it in the weekend...
[edit]
A fast check for primality
Trying to reduce the number of iterations and especially the number of divisions (div
is a costly operation) is what we're after here:
- It is most efficient to split off the small numbers [0,3] first. This avoids extra tests in the loop.
- Next we split off the even numbers because, except for the number 2 (that we already have split off), no even number is prime.
- Therefore the loop only has to divide odd numbers. We can omit all the even divisors at once because dividing an odd number by an even number will never produce a zero remainder.
- We only need to test divisors up to the integer square root of the number. Luckily we don't need to calculate it. As long as the quotient from the division is still greater than the divisor we have not yet reached the integer square root.
; IN (dl) OUT (cx) MOD (ax,bl)
TestPrime:
xor cx, cx ; CX=0 means NotPrime
cmp dl, 4
jb .Less4
mov bl, 1
test dl, bl
jz .No ; Number is EVEN, so not prime
; Remaining candidates {5,7,9,11,13,15,...}
.Loop:
add bl, 2 ; Division by {3,5,7,9,11,....}
mov al, dl
mov ah, 0 ; Will divide AX by BL
div bl
test ah, ah ; Remainder == 0 ?
jz .No ; Yes, found an additional divisor, so not prime
cmp al, bl ; Quotient > divisor ?
ja .Loop ; Yes, continue up to isqrt(number)
.Yes:
inc cx ; CX=1 means Prime
ret
.Less4:
cmp dl, 2
jae .Yes ; 2 and 3 are prime, 0 and 1 are not prime
.No:
ret
Prime numbers smaller than 256
Next table shows the number of DIV
instructions that got executed and the time it took in nanoseconds. The middle columns are for the question's improved code, and the columns on the right are for today's optimized code. As numbers grow, so does the benefit.
Number |
IsPrime |
DIV's |
nsec |
DIV's |
nsec |
251 |
1 |
250 |
4163 |
8 |
495 |
241 |
1 |
240 |
4140 |
8 |
428 |
239 |
1 |
238 |
3967 |
7 |
285 |
233 |
1 |
232 |
3869 |
7 |
263 |
229 |
1 |
228 |
3809 |
7 |
285 |
227 |
1 |
226 |
3779 |
7 |
255 |
223 |
1 |
222 |
3697 |
7 |
263 |
211 |
1 |
210 |
3494 |
7 |
255 |
199 |
1 |
198 |
3298 |
7 |
263 |
197 |
1 |
196 |
3276 |
7 |
263 |
193 |
1 |
192 |
3298 |
7 |
263 |
191 |
1 |
190 |
3186 |
7 |
263 |
181 |
1 |
180 |
3020 |
6 |
315 |
179 |
1 |
178 |
2990 |
6 |
308 |
173 |
1 |
172 |
2900 |
6 |
285 |
167 |
1 |
166 |
2802 |
6 |
232 |
163 |
1 |
162 |
2742 |
6 |
232 |
157 |
1 |
156 |
2667 |
6 |
240 |
151 |
1 |
150 |
2637 |
6 |
240 |
149 |
1 |
148 |
2524 |
6 |
240 |
139 |
1 |
138 |
2382 |
6 |
240 |
137 |
1 |
136 |
2352 |
6 |
240 |
131 |
1 |
130 |
2254 |
5 |
285 |
127 |
1 |
126 |
2171 |
5 |
293 |
113 |
1 |
112 |
1946 |
5 |
255 |
109 |
1 |
108 |
1893 |
5 |
225 |
107 |
1 |
106 |
1871 |
5 |
225 |
103 |
1 |
102 |
1848 |
5 |
210 |
101 |
1 |
100 |
1750 |
5 |
225 |
97 |
1 |
96 |
1713 |
5 |
225 |
89 |
1 |
88 |
1555 |
4 |
270 |
83 |
1 |
82 |
1457 |
4 |
270 |
79 |
1 |
78 |
1465 |
4 |
240 |
73 |
1 |
72 |
1390 |
4 |
195 |
71 |
1 |
70 |
1284 |
4 |
202 |
67 |
1 |
66 |
1202 |
4 |
210 |
61 |
1 |
60 |
1209 |
4 |
195 |
59 |
1 |
58 |
1082 |
4 |
195 |
53 |
1 |
52 |
976 |
3 |
255 |
47 |
1 |
46 |
871 |
3 |
263 |
43 |
1 |
42 |
804 |
3 |
180 |
41 |
1 |
40 |
773 |
3 |
187 |
37 |
1 |
36 |
728 |
3 |
172 |
31 |
1 |
30 |
616 |
3 |
180 |
29 |
1 |
28 |
601 |
2 |
225 |
23 |
1 |
22 |
510 |
2 |
232 |
19 |
1 |
18 |
435 |
2 |
172 |
17 |
1 |
16 |
413 |
2 |
172 |
13 |
1 |
12 |
360 |
2 |
172 |
11 |
1 |
10 |
315 |
1 |
217 |
7 |
1 |
6 |
247 |
1 |
142 |
5 |
1 |
4 |
217 |
1 |
150 |
3 |
1 |
2 |
187 |
0 |
165 |
2 |
1 |
1 |
172 |
0 |
165 |
Non prime numbers smaller than 256
Next table shows the number of DIV
instructions that got executed and the time it took in nanoseconds. The middle columns are for the question's improved code, and the columns on the right are for today's optimized code. As numbers grow, so does the benefit.
Number |
IsPrime |
DIV's |
nsec |
DIV's |
nsec |
255 |
0 |
4 |
270 |
1 |
195 |
254 |
0 |
126 |
2261 |
0 |
202 |
253 |
0 |
22 |
518 |
5 |
345 |
252 |
0 |
2 |
202 |
0 |
180 |
250 |
0 |
4 |
285 |
0 |
142 |
249 |
0 |
82 |
1532 |
1 |
217 |
248 |
0 |
3 |
240 |
0 |
150 |
247 |
0 |
18 |
510 |
6 |
345 |
246 |
0 |
2 |
210 |
0 |
165 |
245 |
0 |
6 |
270 |
2 |
232 |
244 |
0 |
3 |
255 |
0 |
165 |
243 |
0 |
8 |
338 |
1 |
217 |
242 |
0 |
10 |
375 |
0 |
180 |
240 |
0 |
2 |
217 |
0 |
157 |
238 |
0 |
6 |
360 |
0 |
142 |
237 |
0 |
78 |
1442 |
1 |
187 |
236 |
0 |
3 |
240 |
0 |
142 |
235 |
0 |
46 |
916 |
2 |
232 |
234 |
0 |
2 |
210 |
0 |
157 |
232 |
0 |
3 |
180 |
0 |
157 |
231 |
0 |
6 |
270 |
1 |
187 |
230 |
0 |
4 |
247 |
0 |
142 |
228 |
0 |
2 |
210 |
0 |
150 |
226 |
0 |
112 |
2066 |
0 |
142 |
225 |
0 |
4 |
247 |
1 |
195 |
224 |
0 |
3 |
240 |
0 |
142 |
222 |
0 |
2 |
217 |
0 |
150 |
221 |
0 |
16 |
435 |
6 |
338 |
220 |
0 |
3 |
240 |
0 |
150 |
219 |
0 |
72 |
1352 |
1 |
225 |
218 |
0 |
108 |
1931 |
0 |
142 |
217 |
0 |
30 |
646 |
3 |
278 |
216 |
0 |
2 |
210 |
0 |
157 |
215 |
0 |
42 |
924 |
2 |
232 |
214 |
0 |
106 |
1893 |
0 |
165 |
213 |
0 |
70 |
1322 |
1 |
217 |
212 |
0 |
3 |
240 |
0 |
157 |
210 |
0 |
2 |
165 |
0 |
150 |
209 |
0 |
18 |
488 |
5 |
323 |
208 |
0 |
3 |
270 |
0 |
165 |
207 |
0 |
8 |
255 |
1 |
217 |
206 |
0 |
102 |
1893 |
0 |
165 |
205 |
0 |
40 |
811 |
2 |
202 |
204 |
0 |
2 |
210 |
0 |
165 |
203 |
0 |
28 |
631 |
3 |
278 |
202 |
0 |
100 |
1795 |
0 |
165 |
201 |
0 |
66 |
1254 |
1 |
217 |
200 |
0 |
3 |
240 |
0 |
165 |
198 |
0 |
2 |
165 |
0 |
150 |
196 |
0 |
3 |
232 |
0 |
142 |
195 |
0 |
4 |
240 |
1 |
187 |
194 |
0 |
96 |
1750 |
0 |
142 |
192 |
0 |
2 |
165 |
0 |
150 |
190 |
0 |
4 |
315 |
0 |
142 |
189 |
0 |
6 |
270 |
1 |
195 |
188 |
0 |
3 |
255 |
0 |
142 |
187 |
0 |
16 |
428 |
5 |
308 |
186 |
0 |
2 |
202 |
0 |
142 |
185 |
0 |
36 |
804 |
2 |
232 |
184 |
0 |
3 |
240 |
0 |
165 |
183 |
0 |
60 |
1142 |
1 |
225 |
182 |
0 |
6 |
270 |
0 |
157 |
180 |
0 |
2 |
165 |
0 |
157 |
178 |
0 |
88 |
1720 |
0 |
142 |
177 |
0 |
58 |
1134 |
1 |
187 |
176 |
0 |
3 |
240 |
0 |
150 |
175 |
0 |
6 |
270 |
2 |
232 |
174 |
0 |
2 |
210 |
0 |
180 |
172 |
0 |
3 |
240 |
0 |
157 |
171 |
0 |
8 |
300 |
1 |
187 |
170 |
0 |
4 |
247 |
0 |
150 |
169 |
0 |
168 |
2938 |
6 |
345 |
168 |
0 |
2 |
210 |
0 |
165 |
166 |
0 |
82 |
1540 |
0 |
142 |
165 |
0 |
4 |
240 |
1 |
240 |
164 |
0 |
3 |
232 |
0 |
150 |
162 |
0 |
2 |
157 |
0 |
150 |
161 |
0 |
22 |
510 |
3 |
278 |
160 |
0 |
3 |
247 |
0 |
157 |
159 |
0 |
52 |
1014 |
1 |
187 |
158 |
0 |
78 |
1442 |
0 |
142 |
156 |
0 |
2 |
165 |
0 |
142 |
155 |
0 |
30 |
646 |
2 |
263 |
154 |
0 |
6 |
270 |
0 |
150 |
153 |
0 |
8 |
375 |
1 |
187 |
152 |
0 |
3 |
247 |
0 |
157 |
150 |
0 |
2 |
210 |
0 |
150 |
148 |
0 |
3 |
270 |
0 |
150 |
147 |
0 |
6 |
270 |
1 |
202 |
146 |
0 |
72 |
1352 |
0 |
150 |
145 |
0 |
28 |
631 |
2 |
232 |
144 |
0 |
2 |
202 |
0 |
157 |
143 |
0 |
12 |
390 |
5 |
308 |
142 |
0 |
70 |
1375 |
0 |
165 |
141 |
0 |
46 |
916 |
1 |
225 |
140 |
0 |
3 |
240 |
0 |
165 |
138 |
0 |
2 |
165 |
0 |
195 |
136 |
0 |
3 |
232 |
0 |
150 |
135 |
0 |
4 |
247 |
1 |
195 |
134 |
0 |
66 |
1247 |
0 |
142 |
133 |
0 |
18 |
488 |
3 |
308 |
132 |
0 |
2 |
165 |
0 |
172 |
130 |
0 |
4 |
247 |
0 |
187 |
129 |
0 |
42 |
879 |
1 |
195 |
128 |
0 |
3 |
240 |
0 |
165 |
126 |
0 |
2 |
165 |
0 |
142 |
125 |
0 |
24 |
556 |
2 |
263 |
124 |
0 |
3 |
240 |
0 |
165 |
123 |
0 |
40 |
811 |
1 |
150 |
122 |
0 |
60 |
1209 |
0 |
142 |
121 |
0 |
120 |
2134 |
5 |
308 |
120 |
0 |
2 |
210 |
0 |
142 |
119 |
0 |
16 |
473 |
3 |
278 |
118 |
0 |
58 |
1127 |
0 |
165 |
117 |
0 |
8 |
300 |
1 |
202 |
116 |
0 |
3 |
247 |
0 |
172 |
115 |
0 |
22 |
556 |
2 |
270 |
114 |
0 |
2 |
210 |
0 |
165 |
112 |
0 |
3 |
240 |
0 |
150 |
111 |
0 |
36 |
758 |
1 |
187 |
110 |
0 |
4 |
240 |
0 |
157 |
108 |
0 |
2 |
165 |
0 |
150 |
106 |
0 |
52 |
1097 |
0 |
150 |
105 |
0 |
4 |
240 |
1 |
202 |
104 |
0 |
3 |
240 |
0 |
150 |
102 |
0 |
2 |
165 |
0 |
142 |
100 |
0 |
3 |
232 |
0 |
157 |
99 |
0 |
8 |
300 |
1 |
165 |
98 |
0 |
6 |
270 |
0 |
165 |
96 |
0 |
2 |
165 |
0 |
142 |
95 |
0 |
18 |
488 |
2 |
217 |
94 |
0 |
46 |
1036 |
0 |
150 |
93 |
0 |
30 |
646 |
1 |
195 |
92 |
0 |
3 |
240 |
0 |
157 |
91 |
0 |
12 |
390 |
3 |
308 |
90 |
0 |
2 |
210 |
0 |
180 |
88 |
0 |
3 |
232 |
0 |
187 |
87 |
0 |
28 |
631 |
1 |
187 |
86 |
0 |
42 |
871 |
0 |
142 |
85 |
0 |
16 |
428 |
2 |
232 |
84 |
0 |
2 |
210 |
0 |
180 |
82 |
0 |
40 |
819 |
0 |
157 |
81 |
0 |
8 |
293 |
1 |
202 |
80 |
0 |
3 |
232 |
0 |
142 |
78 |
0 |
2 |
210 |
0 |
157 |
77 |
0 |
10 |
323 |
3 |
278 |
76 |
0 |
3 |
232 |
0 |
142 |
75 |
0 |
4 |
240 |
1 |
150 |
74 |
0 |
36 |
758 |
0 |
150 |
72 |
0 |
2 |
165 |
0 |
142 |
70 |
0 |
4 |
315 |
0 |
142 |
69 |
0 |
22 |
518 |
1 |
187 |
68 |
0 |
3 |
240 |
0 |
142 |
66 |
0 |
2 |
165 |
0 |
142 |
65 |
0 |
12 |
390 |
2 |
232 |
64 |
0 |
3 |
240 |
0 |
142 |
63 |
0 |
6 |
270 |
1 |
150 |
62 |
0 |
30 |
646 |
0 |
150 |
60 |
0 |
2 |
165 |
0 |
150 |
58 |
0 |
28 |
751 |
0 |
142 |
57 |
0 |
18 |
488 |
1 |
195 |
56 |
0 |
3 |
270 |
0 |
165 |
55 |
0 |
10 |
368 |
2 |
232 |
54 |
0 |
2 |
202 |
0 |
180 |
52 |
0 |
3 |
240 |
0 |
157 |
51 |
0 |
16 |
428 |
1 |
195 |
50 |
0 |
4 |
240 |
0 |
142 |
49 |
0 |
48 |
1044 |
3 |
270 |
48 |
0 |
2 |
210 |
0 |
165 |
46 |
0 |
22 |
593 |
0 |
157 |
45 |
0 |
4 |
240 |
1 |
187 |
44 |
0 |
3 |
240 |
0 |
165 |
42 |
0 |
2 |
202 |
0 |
142 |
40 |
0 |
3 |
270 |
0 |
142 |
39 |
0 |
12 |
398 |
1 |
187 |
38 |
0 |
18 |
488 |
0 |
142 |
36 |
0 |
2 |
210 |
0 |
150 |
35 |
0 |
6 |
270 |
2 |
247 |
34 |
0 |
16 |
420 |
0 |
150 |
33 |
0 |
10 |
323 |
1 |
187 |
32 |
0 |
3 |
232 |
0 |
142 |
30 |
0 |
2 |
202 |
0 |
150 |
28 |
0 |
3 |
263 |
0 |
165 |
27 |
0 |
8 |
293 |
1 |
195 |
26 |
0 |
12 |
465 |
0 |
142 |
25 |
0 |
24 |
563 |
2 |
232 |
24 |
0 |
2 |
210 |
0 |
142 |
22 |
0 |
10 |
323 |
0 |
150 |
21 |
0 |
6 |
270 |
1 |
202 |
20 |
0 |
3 |
232 |
0 |
150 |
18 |
0 |
2 |
225 |
0 |
150 |
16 |
0 |
3 |
232 |
0 |
157 |
15 |
0 |
4 |
232 |
1 |
187 |
14 |
0 |
6 |
263 |
0 |
142 |
12 |
0 |
2 |
217 |
0 |
157 |
10 |
0 |
4 |
315 |
0 |
157 |
9 |
0 |
8 |
308 |
1 |
217 |
8 |
0 |
3 |
247 |
0 |
150 |
6 |
0 |
2 |
217 |
0 |
142 |
4 |
0 |
3 |
240 |
0 |
165 |
1 |
0 |
0 |
165 |
0 |
187 |
0 |
0 |
0 |
157 |
0 |
187 |