2

I'm fairly new to assembly, and I'm trying to print out the prime factorization of a given number. After hours of scouring the net, I've found some useful tidbits about the DIV instruction, but I can't get my code to do what I want.

I've done something terribly wrong, but I can't spot it. Can some kind person spot it for me, please?

.data
myMessage BYTE "Please enter a number to be evaluated:",0dh,0ah,0
factor DWORD 2
hold DWORD ?
.code
main PROC
    call Clrscr  

    mov  edx,offset myMessage
    call WriteString            ;Displays myMessage
    call ReadDec                ;Puts value into EAX register
    mov edi, factor
    call prime


    exit
main ENDP

prime PROC

step1:  xor edx, edx
        div edi
        cmp edx, 1
        jz step2
        add factor, 1
        mov edi, factor
        jmp step1

step2:  mov hold, eax
        mov eax, edi
        call WriteDec
        mov eax, hold
        CMP eax, 1
        jz step3
        jmp step1

step3:  
        exit
prime ENDP


END main
Matthew Slattery
  • 45,290
  • 8
  • 103
  • 119
Shesho
  • 49
  • 3
  • 6

1 Answers1

1

If I understand what you are trying to do, I think you have a misunderstanding of how cmp and jz work.

cmp works by subtracting the source (second) operand from the destination (first) without storing the result, and setting flags based on the result. For unsigned numbers, the relevant flags are carry and zero. If the source was bigger than the destination, then the subtraction will borrow from its highest position, which has the result of setting the carry flag. If the source and destination are the same, then the result will be zero, and the zero flag will be set. If the source is smaller than the destination, then the subtraction won't result in 0 or cause a carry, so both flags will be 0.

The jz (and other conditional jumps) perform a jump depending on the current state of the flags. Specifically, jz will perform the jump if the zero flag is set. Since cmp sets the zero flag to indicate that its operands were equal, the jump if equal (je) instruction is actually the same as the jump is zero instruction. The jump if carry (jc) and jump if below (jb) instructions are also the same, for the same reason.

Since cmp sets the flags to indicate which operand was bigger, the jz instruction can be confusing. It will jump if the operands were equal, not if one of them was zero. Looking at your code from step1:

div edi
cmp edx, 1
jz step2

I think what you are trying to do is jump to step2 if the remainder of the division is 0, but due to the way cmp works, you will actually jump to step2 if the remainder is 1. The fix is simple: change the 1 to 0. (Note: I changed jz to je because it better explains the reason for the jump. As I stated earlier, they are exactly the same.)

div edi
cmp edx, 0
je step2

Additionally, you don't preserve the old value in the case where you don't find a factor. For example, if the input value was 3, your step1 loop would work like this:

  1. Start: eax=3, edi=2
  2. Divide eax by edi. Store the quotient in eax and the remainder in edx.
    • Now, eax=3/2=1, and edx=3%2=1
  3. Is edx 0? If so, print edi and go to the beginning of the loop.
    • It isn't, so continue.
  4. Add 1 to edi. It is now 3.
  5. Perform step 2 with the new values, eax=1 and edi=3.
    • Now, eax=1/3=0, edx=1%3=1
  6. ...

Notice that, even though you didn't find a factor, the value of eax has changed. What you need to do is save its value before you do the division. You can use your hold variable for this, which will mean it is already updated whenever you find a factor. All you have to do is store the value before starting your loop, and restore it at the beginning of each loop.

        mov hold, eax
step1:  mov eax, hold
        xor edx, edx
        ...
ughoavgfhw
  • 39,734
  • 6
  • 101
  • 123