0

I'm attempting to complete a program that takes an unsigned 32-bit integer from user input and tells the user if the number is or isn't prime. I have succeeded in inputting a number--InputNumber--and I have succeeded in using 0 to end the program, but I am struggling with my isPrime procedure, which takes a number n and checks to see if it is prime or not. I keep receiving the error "IntegerOverflow" at line 122 (or div eax), which is supposed to be the result of dividing ECX by 2 in order to make a maximum divisor for n. I'm not sure what else I've done wrong, but it's currently the only error that I've seen (as Visual Studio comes to a grinding halt at line 122). My code is listed below.

TITLE Determine Whether Number is Prime, Version 1 (isPrime.asm)

; This program takes 32-bit unsigned 
; integers and sees if they are prime numbers;
; it also displays the time taken to determine
; this information.
; Name: Kasizah
; Date: 11-07-2022

INCLUDE Irvine32.inc

.data
dPrompt BYTE    "Enter a non-negative integer (0 to exit): ",0
n       DWORD   ?

; time data
startTime   DWORD   ?   ; start time
timeTaken   DWORD   ?   ; time taken to perform process

; message strings
notPositive BYTE    "ERROR: 'n' must be positive.",0
numPrime    BYTE    " is a prime number.",0
notPrime    BYTE    " is not a prime number; it is divisible by ",0
endstr      BYTE    ".",0
nEqualsOne  BYTE    "1 is not a prime number.",0
timeTakenSt BYTE    "This computation took ",0
timeTakenEn BYTE    " milliseconds.",0

.code
main PROC
    input:
        call InputNumber            ; checks to see if number is zero
        cmp  n,0                    ; compare value to zero
        jl   LTZError               ; go to process for error message that 
                                    ;       states that number must be positive
        ja   process                ; if positive, jump to process
        jmp  quit                   ; else number is zero
    LTZError:
        mov  edx,OFFSET notPositive ; state that 'n' must be positive
        call WriteString
        call Crlf                   ; jump to next line
        jmp  input                  ; return to input
    process:
        call GetMseconds            ; get start time
        mov  startTime,eax
        cmp  n,1                    ; if 'n' is 1, jump to notPrimeNum
        je   numIsOne               ; jump to numIsOne
        call isPrime                ; else call isPrime to see if number is prime
        ; jump based on whether or not 'n' is prime
        cmp  eax,0
        jz   primeNum               ; EAX is 0, number is prime
        jmp  notPrimeNum            ; else, say that number isn't prime
    
    ; PRIME OR NOT PRIME STATMENTS
    primeNum:
        mov  eax,n                  ; number is prime
        call WriteInt
        mov  edx,OFFSET numPrime    ; state that number is prime
        call WriteString
        call Crlf                   ; jump to next line
        jmp  getTime                ; jump to getTime
    notPrimeNum:
        mov  ebx,eax                ; copy number stored in EAX
        mov  eax,n                  ; write 'n'
        call WriteInt
        mov  edx,OFFSET notPrime    ; load notPrime into EDX
        call WriteString
        mov  eax,ebx                ; move EBX back into EAX
        call WriteInt
        mov  edx,OFFSET endstr      ; move endstr into EDX
        call WriteString
        call Crlf                   ; jump to next line
        jmp  getTime                ; jump to getTime
    numIsOne:
        mov  edx,OFFSET nEqualsOne  ; load nEqualsOne into EDX
        call WriteString
        call Crlf                   ; jump to next line
        jmp  getTime                ; jump to getTime
    
    ; SEE HOW MUCH TIME WAS TAKEN
    getTime:
        call GetMseconds            ; get process end time
        sub  eax,startTime          ; subtract startTime from time received
        mov  ebx,1000               ; multiply EAX by 1000
        mul  ebx
        ; output time taken
        mov  edx,OFFSET timeTakenSt ; load timeTakenSt into EDX
        call WriteString
        call WriteInt               ; output time as integer
        mov  edx,OFFSET timeTakenEn ; load timeTakenEn into EDX
        call WriteString
        call Crlf                   ; jump to next line
        jmp  input                  ; return to input
    quit:
        exit                        ; exit the program
main ENDP
;----------------------------------------------
InputNumber PROC
;
; Prompts the user to input a number. The
;   number is saved for later use.
; Receives: nothing
; Returns: nothing
;----------------------------------------------
    mov  edx,OFFSET dPrompt ; display prompt
    call WriteString
    call ReadInt            ; reads 32-bit integer in from keyboard
    mov  n,eax              ; move EAX into n
    ret
InputNumber ENDP
;----------------------------------------------
isPrime PROC
;
; Takes a 32-bit number and determines if 
;   it is prime.
; Receives: EAX
; Returns: EAX
;----------------------------------------------
    mov  edx,n              ; move 'n' into EDX
    mov  eax,2              ; move 2 into EAX
    div  eax                ; divide EDX by 2
    mov  ecx,eax            ; move EAX into ECX
    check_loop:
        mov  eax,n              ; move 'n' into EAX
        xor  edx,edx            ; reset EDX to 0 so that it doesn't interfere
        div  ecx                ; divide EAX by ECX
        test edx,edx            ; testing EDX against itself will set the zero flag 
                                ;       if EDX is zero
        jz   not_prime          ; EDX is zero, jump to not_prime
        cmp  ecx,1              ; else check to see if ECX is 1
        je   end_loop           ; if 1, end loop
    not_prime:
        mov  eax,ecx            ; store ECX in EAX
        jmp  quit               ; quit process
    end_loop:
        mov  eax,0              ; as loop ran until ECX equaled 1, 'n' must 
                                ;       be prime; set EAX to 0
        jmp quit                ; quit process
    quit:
        ret
isPrime ENDP
END main
Kasizah
  • 39
  • 4
  • 1
    `div eax` doesn't divide `edx` by `eax`. `div reg32` divides 64-bit number in `edx:eax` pair by value in `reg32` and places quotient to `eax` and remainder to `edx`. So you are trying to divide `n*2^32+2` by 2, obviously quotient doesn't fit into 32-bit `eax`. – dimich Nov 07 '22 at 22:19
  • `xor edx, edx` before the `div eax`, just like you do a few lines before (you also need to move `mov edx, n`). Or just do `shr eax, 1` to divide `eax` by 2. – Margaret Bloom Nov 07 '22 at 22:43

0 Answers0