1

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
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
dami1025
  • 25
  • 4
  • 1
    Have you tried push & pop instead? push each at the beginning and pop them at the end (in the reverse order pushed). – Erik Eidt Feb 25 '23 at 18:49
  • @ErikEidt I have tried push and pop but I don't think I know where to place them correctly, it stopped the program after printing 2 values – dami1025 Feb 25 '23 at 19:01
  • Push immediately upon function entry and pop as the last before ret. – Erik Eidt Feb 25 '23 at 20:44

1 Answers1

2
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

Sep Roland
  • 33,889
  • 7
  • 43
  • 76