我编写了一个汇编程序,我的目标是打印出用户输入的素数。用户只需输入一个数字,例如 15,就会打印前 15 个素数。用户可以输入的范围是 1 到 200 之间。
我的错误捕获功能有效,因此输入低于 1 或高于 200 的任何数字都会重新提示输入另一个数字,但是当我输入一个应该有效的正确范围内的数字时,不会打印任何内容,并且程序几乎停止在它的轨迹,但并没有结束。任何帮助将不胜感激,这是我现在拥有的代码。
INCLUDE Irvine32.inc
; Constant definitions
LOWER_BOUND = 1
UPPER_BOUND = 200
.data
; All text prompts and statements
nameAndProgram BYTE "Prime Numbers Programmed by Norman O'Brien", 13, 10, 0
promptPt1 BYTE "Enter the number of prime numbers you would like to see.", 13, 10, 0
promptPt2 BYTE "I'll accept orders for up to 200 primes.", 13, 10, 0
enterNumberOf BYTE "Enter the number of primes to display [1 ... 200]: ", 0
outOfRange BYTE "No primes for you! Number out of range. Try again.", 13, 10, 0
certified BYTE "Results certified by Norman O'Brien. Goodbye.", 13, 10, 0
spacer BYTE " ", 0 ; This is for separating the prime numbers when it is printed
; Variables
validNum DWORD 0
userInput SDWORD ?
.code
main PROC
call introduction
call getUserData
call showPrimes
call farewell
Invoke ExitProcess,0 ; exit to operating system
main ENDP
introduction PROC
; Print the my name and program name
MOV EDX, OFFSET nameAndProgram
call WriteString
call CrLf
; Print first part of prompt info
MOV EDX, OFFSET promptPt1
call WriteString
; Print second part of prompt info
MOV EDX, OFFSET promptPt2
call WriteString
call CrLf
ret
introduction ENDP
getUserData PROC
top:
MOV EDX, OFFSET enterNumberOf
call WriteString
call ReadInt
MOV userInput, EAX
call validate
MOV EAX, validNum
CMP EAX, 0
JE top
ret
getUserData ENDP
validate PROC
MOV EBX, userInput
CMP EBX, LOWER_BOUND
JL rangeError
CMP EBX, UPPER_BOUND
JG rangeError
JL valid
rangeError:
MOV EDX, OFFSET outOfRange
call WriteString
JMP ending
valid:
MOV EAX, 1
MOV validNum, EAX
ending:
ret
validate ENDP
showPrimes PROC
MOV EBX, userInput ; set EBX to number of primes
MOV ECX, 0 ; counter, start at 0
MOV EAX, 2 ; EAX starts at 2 because it is the first prime
printPrime:
; checks if the current number is a prime number
PUSH EAX ; push current number to stack
CALL isPrime
POP EAX ; restores number from stack after it is checked by isPrime
CMP EAX, 1 ; check if the number is prime
JNE notPrime ; if it's not prime, skip displaying
; display the prime number
CALL WriteDec
MOV EDX, OFFSET spacer
call WriteString
INC ECX ; increment prime count
; after 10 primes have been printed, make new line and reset the count
CMP ECX, 10
JNE nextPrime ; go to next prime if 10 have not been displayed
CALL CrLf
MOV ECX, 0 ; reset count
CMP ECX, EBX ; see if enough primes have been displayed based on the user input (EBX)
JL printPrime ; display the next prime if not
ret
nextPrime:
INC EAX ; move on to the next number by incrementing EAX
JMP printPrime
; if not prime just move on to the next number
notPrime:
INC EAX
JMP printPrime
ret
showPrimes ENDP
isPrime PROC
MOV ECX, 2 ; checking for the primes will start at 2
; 1 does not count as prime, so jump to notPrime if that is the case
CMP EAX, 1
JLE notPrime
checkDivisor:
; divide the number in EAX by the current divisor (ECX) and if there is
; no remainder, then the number is not prime, so jump to notPrime
MOV EDX, 0
DIV ECX
CMP EDX, 0
JE notPrime
; increment the divisor and see if we have checked all possible divisors
; when we compare, if total number of divisors is great than the input (ECX > EAX), it's prime
INC ECX
CMP ECX, EAX
JG prime
JMP checkDivisor
notPrime:
MOV EAX, 0
ret
prime:
MOV EAX, 1
ret
isPrime ENDP
farewell PROC
MOV EDX, OFFSET certified
call WriteString
ret
farewell ENDP
END main
MOV EBX, userInput ; set EBX to number of primes
; ....
MOV ECX, 0 ; reset count
CMP ECX, EBX ; <- ???