cmp ax,1
je perfecto
Why do you consider 1 to be a perfect number?
The wikipedia article https://en.wikipedia.org/wiki/Perfect_number uses the following definition:
In number theory, a perfect number is a positive integer that is equal to the sum of its positive divisors, excluding the number itself. For instance, 6 has divisors 1, 2 and 3 (excluding itself), and 1 + 2 + 3 = 6, so 6 is a perfect number.
The number 1 has but one divisor (1) and that's the one that the definition wants you to exclude. What remains is nothing and that is clearly not equal to the number 1.
Moreover that Wikipedia article also mentions that there probably are no odd perfect numbers.
Why the code fails
The idea behind your code is to divide the inputted number N by all of the numbers in the range [N-1, 1]. Upon finding a zero remainder, you add the current divisor to your sum variable BX
. This is not optimal, but it can work. However, because you neglect to reload the original number, you are not dividing the inputted number but rather the quotient that you got from the previous division. It seemingly works for the number 6 because its 3 divisors follow each other closely and are the final 3 iterations of the loop.
AX DX
6 / 5 -> Q=1 R=1
1 / 4 -> Q=0 R=1
0 / 3 -> Q=0 R=0 -> BX=0+3=3
0 / 2 -> Q=0 R=0 -> BX=3+2=5
0 / 1 -> Q=0 R=0 -> BX=5+1=6 OK
Now consider 28:
AX DX
28 / 27 -> Q=1 R=1
1 / 26 -> Q=0 R=1
0 / 25 -> Q=0 R=0 -> BX=0+25=25
0 / 24 -> Q=0 R=0 -> BX=25+24=49
0 / 23 -> Q=0 R=0 -> BX=49+23=72
0 / 22 -> Q=0 R=0 -> BX=72+22=94
0 / 21 -> Q=0 R=0 -> BX=94+21=115 ???
...
A solution
- Better start dividing at half the inputted number. Larger divisors will never produce a zero remainder.
- Better no do that final division by 1. It will always produce a zero remainder. Just
inc bx
in the end. Or even better initialize the running sum at 1 instead of 0.
- Better write the division loop with a single conditional branch instruction instead of a conditional exit branch and an unconditional repeat branch.
mov bx, 1 ; Running sum
mov cx, _x$ ; Inputted number
shr cx, 1 ; First divisor is N/2
jz NotPerfect ; N=0 or N=1
next:
mov ax, _x$ ; RELOADING NUMBER
xor dx, dx
div cx
dec cx ; (*)
test dx, dx
jnz next
add bx, cx
inc bx ; (*) Because CX got already decremented
cmp cx, 1
ja next
AX DX
28 / 14 -> Q=2 R=0 -> BX=1+(13+1)=15
28 / 13 -> Q=2 R=2
28 / 12 -> Q=2 R=4
28 / 11 -> Q=2 R=6
28 / 10 -> Q=2 R=8
28 / 9 -> Q=2 R=10
28 / 8 -> Q=3 R=4
28 / 7 -> Q=4 R=0 -> BX=15+(6+1)=22
28 / 6 -> Q=4 R=4
28 / 5 -> Q=5 R=3
28 / 4 -> Q=7 R=0 -> BX=22+(3+1)=26
28 / 3 -> Q=9 R=1
28 / 2 -> Q=14 R=0 -> BX=26+(1+1)=28 OK