Search code examples
assemblyx86masmcalling-convention

MASM Printing prime numbers


Hi so I'm having problem with my Assembly project. I am supposed to print out x prime numbers in order. But I cannot use the fuction USES. When I tried to remove it, I got an infinite loop. Can someone please help me, thank you

isPrime PROC USES ECX EBX
; Checks whether a number is prime or not. If given number is prime, returns
; boolean value 1. Otherwise, returns 0.
; receives: A number in EAX
; returns: boolean value(0 or 1) in EAX
; preconditions: eax is in [1..200]
; registers changed: eax, ebx, ecx, edx
;-------------------------------------------------------------------------
        mov ecx,eax                         ; copy the number p into ECX
        mov esi, 2                          ; i=2
  startLoop:
        cmp esi,ecx                         
        jge PrimeNum                        ; if i>=p, p is prime and goto PrimeNum
        mov edx,0
        mov eax,ecx
        div esi                             ; calculate p/i. EAX=p/i and EDX=p%i
        cmp edx, 0                          
        je  NotPrime                        ; if remainder = 0, p is not prime
        inc esi                             ; otherwise, continue search
        jmp startLoop
PrimeNum:   
    mov eax, TRUE                           ; if p is prime , return true
    ret
NotPrime:
    mov eax, FALSE                          ; if p is not prime, return true
    ret
isPrime ENDP

When I removed the USES part

mov ecx,eax                         ; copy the number p into ECX
        mov try2, 2                         ; i=2
  startLoop:
        cmp try2,ecx                            
        jge PrimeNum                        ; if i>=p, p is prime and goto PrimeNum
        mov edx,0
        mov eax,ecx
        div try2                                ; calculate p/i. EAX=p/i and EDX=p%i
        cmp edx, 0                          
        je  NotPrime                        ; if remainder = 0, p is not prime
        inc try2                                ; otherwise, continue search
        jmp startLoop
PrimeNum:   
    mov eax, TRUE                           ; if p is prime , return true
    
    
    ret
NotPrime:
    mov eax, FALSE                          ; if p is not prime, return true
    ret

Solution

  • isPrime PROC USES ECX EBX
    

    Although this claims to be using EBX, the code actually uses ESI and doesn't even touch EBX.

    If you don't want to rely on USES, you'll need to preserve the registers that you want to keep or that need preserving. Because your code has multiple ret instructions, you also need multiple restoration sequences:

    isPrime PROC
        push ecx         ;
        push edx         ; Preserves ECX EDX ESI
        push esi         ;
        mov  ecx, eax    ; copy the number p into ECX
        mov  esi, 2      ; i=2
      startLoop:
        cmp  esi, ecx                          
        jge  PrimeNum    ; if i>=p, p is prime and goto PrimeNum
        mov  edx, 0
        mov  eax, ecx
        div  esi         ; calculate p/i. EAX=p/i and EDX=p%i
        cmp  edx, 0                          
        je   NotPrime    ; if remainder = 0, p is not prime
        inc  esi         ; otherwise, continue search
        jmp  startLoop
      PrimeNum:   
        mov  eax, TRUE   ; if p is prime , return true
        pop  esi         ;
        pop  edx         ; Restores ESI EDX ECX
        pop  ecx         ;
        ret
      NotPrime:
        mov  eax, FALSE  ; if p is not prime, return true
        pop  esi         ;
        pop  edx         ; Restores ESI EDX ECX
        pop  ecx         ;
        ret
    isPrime ENDP
    

    It would be easy to avoid this double ret:

    isPrime PROC
        push ecx         ;
        push edx         ; Preserves ECX EDX ESI
        push esi         ;
        mov  ecx, eax    ; copy the number p into ECX
        mov  esi, 2      ; i=2
      startLoop:
        mov  eax, TRUE   ; if p is prime , return true
        cmp  esi, ecx                          
        jge  PrimeNum    ; if i>=p, p is prime and goto PrimeNum
        mov  edx, 0
        mov  eax, ecx
        div  esi         ; calculate p/i. EAX=p/i and EDX=p%i
        cmp  edx, 0                          
        je   NotPrime    ; if remainder = 0, p is not prime
        inc  esi         ; otherwise, continue search
        jmp  startLoop
      NotPrime:
        mov  eax, FALSE  ; if p is not prime, return true
      PrimeNum:   
        pop  esi         ;
        pop  edx         ; Restores ESI EDX ECX
        pop  ecx         ;
        ret
    isPrime ENDP
    

    This code is still not optimal for checking primality. You can find more ideas about a fast check for primality in this answer