Reputation: 11
I'm having trouble trying to display the correct values for Min, Max, Sum, and Average of user-inputted negative integers. When I run my code and enter two negative values (-10 and -30), here are the results (user inputs in bold):
Welcome to the Integer Accumulator by John
We will be accumulating user-input negative integers between the specified bounds, then displaying statistics of the
input values including minimum, maximum, and average values values, total sum, and total number of valid inputs.
What is your name? **John**
Hello there, John
Please enter numbers in [-200, -100] or [-50, -1].
Enter a non-negative number when you are finished, and input stats will be shown.
Enter number: **-10**
Enter number: **-30**
Enter number: 0
You entered 2 valid numbers.
The sum of your valid numbers is 4294967256
The maximum valid number is 4294967286
The minimum valid number is 4294967196
The rounded average is 4294967276
We have to stop meeting like this. Farewell, John
Do you see how the sum, min, max, and average of the numbers are all incorrect? That's what I'm trying to fix. The expected output should be:
The sum of your valid numbers is -40
The maximum valid number is -10
The minimum valid number is -30
The rounded average is -20
Here's the code below. I also may need to change the numAverage data variable to be a float, but I have not tested it yet:
INCLUDE Irvine32.inc
.data
titleMsg BYTE "Welcome to the Integer Accumulator by ", 0
myName BYTE "John", 0
progMsg BYTE "We will be accumulating user-input negative integers between the specified bounds, then displaying statistics of the ", 0
progMsg2 BYTE "input values including minimum, maximum, and average values values, total sum, and total number of valid inputs.", 0
namePrompt BYTE "What is your name? ", 0
greetMsg BYTE "Hello there, ", 0
instruction BYTE "Please enter numbers in [-200, -100] or [-50, -1].", 0
instruction2 BYTE "Enter a non-negative number when you are finished, and input stats will be shown.", 0
invalidMsg BYTE "This is not a number we're looking for (Invalid Input)!", 0
inputPrompt BYTE "Enter number: ", 0
statsMsg BYTE "You entered ", 0
validMsg BYTE " valid numbers.", 0
maxMsg BYTE "The maximum valid number is ", 0
minMsg BYTE "The minimum valid number is ", 0
sumMsg BYTE "The sum of your valid numbers is ", 0
avgMsg BYTE "The rounded average is ", 0
farewellMsg BYTE "We have to stop meeting like this. Farewell, ", 0
specialMsg BYTE "Congratulations, you found an Easter Egg!", 0
SUM_LIMIT EQU 1000 ; Limit for the sum of numbers entered
; Constants for value limits
LOWER_BOUND1 EQU -200
UPPER_BOUND1 EQU -100
LOWER_BOUND2 EQU -50
UPPER_BOUND2 EQU -1
; Variables
userName BYTE 50 DUP (?)
inputNumber SDWORD ?
validCount DWORD ?
numSum SDWORD ?
numMax SDWORD ?
numMin SDWORD ?
numAverage SDWORD ?
signFlag BYTE ?
.code
main PROC
; Display program title and programmer's name
mov edx, OFFSET titleMsg
call WriteString
mov edx, OFFSET myName
call WriteString
call Crlf
; Display program description
mov edx, OFFSET progMsg
call WriteString
call Crlf
mov edx, OFFSET progMsg2
call WriteString
call Crlf
; Get the user's name and greet the user
mov edx, OFFSET namePrompt
call WriteString
mov edx, OFFSET userName
mov ecx, SIZEOF myName
call ReadString
mov edx, OFFSET greetMsg
call WriteString
mov edx, OFFSET userName
call WriteString
call Crlf
call Crlf
; Display instructions
mov edx, OFFSET instruction
call WriteString
call CrLf
mov edx, OFFSET instruction2
call WriteString
call CrLf
; Initialize variables
mov numSum, 0
mov validCount, 0
mov numMax, LOWER_BOUND1 ; Initialize to the smallest possible value
mov numMin, UPPER_BOUND1 ; Initialize to the largest possible value
; User input loop
inputLoop:
; Prompt user to enter a number
mov edx, OFFSET inputPrompt
call WriteString
call ReadInt
mov inputNumber, eax
; Check if the number is non-negative
test eax, eax
jns checkSpecialMessage
; Check if the number is within the specified ranges
cmp inputNumber, LOWER_BOUND1
jl invalidInput
cmp inputNumber, UPPER_BOUND1
jg checkSecondRange
jmp validInput
checkSecondRange:
cmp inputNumber, LOWER_BOUND2
jl invalidInput
cmp inputNumber, UPPER_BOUND2
jg invalidInput
jmp validInput
invalidInput:
; Notify user of invalid input
mov edx, OFFSET invalidMsg
call WriteString
call CrLf
jmp inputLoop
validInput:
; Update count and sum of valid numbers
inc validCount
mov eax, inputNumber ; Move inputNumber into eax register
add numSum, eax ; Add eax (inputNumber) to numSum
; Update max and min valid numbers
mov eax, numMax ; Move numMax into eax register
cmp inputNumber, eax ; Compare inputNumber with eax (numMax)
jle notMax
mov eax, inputNumber ; Move inputNumber into eax register
mov numMax, eax ; Move eax (inputNumber) to numMax
notMax:
mov eax, numMin ; Move numMin into eax register
cmp inputNumber, eax ; Compare inputNumber with eax (numMin)
jge notMin
mov eax, inputNumber ; Move inputNumber into eax register
mov numMin, eax ; Move eax (inputNumber) to numMin
notMin:
jmp inputLoop
checkSpecialMessage:
; Check if any valid inputs were received
cmp validCount, 0
je displaySpecialMessage ; If no valid inputs were received, display special message
jmp displayStats ; If valid inputs were received, display statistics
displaySpecialMessage:
; Display special message
mov edx, OFFSET specialMsg
call WriteString
call CrLf
; Display farewell message with the user's name
mov edx, OFFSET farewellMsg
call WriteString
mov edx, OFFSET userName
call WriteString
displayStats:
; Calculate the rounded average
mov eax, numSum
cdq
idiv validCount
mov numAverage, eax
; Display statistics
mov edx, OFFSET statsMsg
call WriteString
mov eax, validCount
call WriteDec
mov edx, OFFSET validMsg
call WriteString
call CrLf
mov edx, OFFSET sumMsg
call WriteString
mov eax, numSum
call WriteDec
call CrLf
mov edx, OFFSET maxMsg
call WriteString
mov eax, numMax
call WriteDec
call CrLf
mov edx, OFFSET minMsg
call WriteString
mov eax, numMin
call WriteDec
call CrLf
mov edx, OFFSET avgMsg
call WriteString
mov eax, numAverage
call WriteDec
call CrLf
; Display farewell message with the user's name
mov edx, OFFSET farewellMsg
call WriteString
mov edx, OFFSET userName
call WriteString
exit
main ENDP
END main
Upvotes: 1
Views: 50
Reputation: 39166
Comparing what you were expecting:
The sum of your valid numbers is -40 The maximum valid number is -10 The minimum valid number is -30 The rounded average is -20
with what you got:
The sum of your valid numbers is 4294967256 The maximum valid number is 4294967286 The minimum valid number is 4294967196 The rounded average is 4294967276
it is immediately clear that you are outputting these signed results as unsigned numbers.
A closer look at the value 4294967196 for the minimum valid number also reveals that there has to be an error somewhere in the program (because -30 ought to have displayed as 4294967266).
You are using the wrong Irvine32 function. Instead of WriteDec
that is meant to output unsigned 32-bit integers, use WriteInt
to output signed 32-bit integers.
You have initialized numMin to UPPER_BOUND1 but that is not the largest possible value (although you state it in your comment). The truly largest possible value is the -1 from the UPPER_BOUND2 equate, so correct it with:
mov numMax, LOWER_BOUND1 ; Initialize to the smallest possible value -200
mov numMin, UPPER_BOUND2 ; Initialize to the largest possible value -1
Once a variable has been loaded in a register, it remains available from that register (until you make changes to the register of course). In the following snippet I have marked the lines where you can and most certainly should replace inputNumber by EAX:
mov inputNumber, eax
test eax, eax
jns checkSpecialMessage
cmp inputNumber, LOWER_BOUND1 cmp eax, LOWER_BOUND1
jl invalidInput
cmp inputNumber, UPPER_BOUND1 cmp eax, UPPER_BOUND1
jg checkSecondRange
jmp validInput
checkSecondRange:
cmp inputNumber, LOWER_BOUND2 cmp eax, LOWER_BOUND2
jl invalidInput
cmp inputNumber, UPPER_BOUND2 cmp eax, UPPER_BOUND2
jg invalidInput \ jng validInput
jmp validInput / ; else fall-through
invalidInput:
mov edx, OFFSET invalidMsg
call WriteString
call CrLf
jmp inputLoop
validInput:
inc validCount
mov eax, inputNumber Remove this, EAX still has inputNumber
add numSum, eax
mov eax, numMax Remove this, No need to load/clobber EAX
cmp inputNumber, eax Then write this as: cmp eax, numMax
jle notMax
mov eax, inputNumber Remove this, EAX still has inputNumber
mov numMax, eax
notMax:
mov eax, numMin Remove this, No need to load/clobber EAX
cmp inputNumber, eax Then write this as: cmp eax, numMin
jge notMin
mov eax, inputNumber Remove this, EAX still has inputNumber
mov numMin, eax
notMin:
jmp inputLoop
In a copy-paste fashion (and you won't believe how many bytes you will have shaved off):
mov inputNumber, eax
test eax, eax
jns checkSpecialMessage
cmp eax, LOWER_BOUND1
jl invalidInput
cmp eax, UPPER_BOUND1
jg checkSecondRange
jmp validInput
checkSecondRange:
cmp eax, LOWER_BOUND2
jl invalidInput
cmp eax, UPPER_BOUND2
jng validInput
invalidInput:
mov edx, OFFSET invalidMsg
call WriteString
call CrLf
jmp inputLoop
validInput:
inc validCount
add numSum, eax
cmp eax, numMax
jle notMax
mov numMax, eax
notMax:
cmp eax, numMin
jge notMin
mov numMin, eax
notMin:
jmp inputLoop
Upvotes: 0