News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Calculating Mean

Started by usafman2006, November 26, 2011, 03:38:19 AM

Previous topic - Next topic

usafman2006

For this project, I am supposed to calculate the first 94 fibonacci numbers & store them in an array.  Then prompt the user to either: 1) display all or part of the array, 2) display the mean or all or part of the array, 3) display all or part of the standard deviation of the array, 4) calculate the square root of a real number, or 5) quit.  Three of the five items work, but I'm having issues with the mean and standard deviation procedures.  Any help would be greatly appreciated.


TITLE PROG4.asm                ;File name of program

MAXSTR equ 256d    ;maximum length of input string
LF equ 10d    ;line feed character
CR equ 13d    ;carrage return character
NL equ LF,CR    ;combined line feed and return
DOUBLESPC equ LF,LF,CR    ;used to produce double spacing
TRUE equ 1h                    ;boolean flag
FALSE equ 0h                   ;boolean flag

INCLUDE io64.inc    ;required for I/O routines
INCLUDE fpu_io64.inc           ;required for 64-bit FPU instructions

.DATA
    Intro      BYTE NL,    'This program will calculate the first 94 Fibonacci numbers and store', NL, \
                               'them in an array. The user will then be able to print or display', NL, \
                               'the mean or standard deviation of all or any part of the array.',NL, \
                               'The program will also calculate the square root of a real number.',NL, 0

        Menu       BYTE NL,NL, '             Fibonacci Fun', NL, NL, \
                               '1) Display ALL or any PART of the Fibonacci Array', NL, \
                               '2) Display the "Mean" of ALL or any PART of the Array', NL, \
                               '3) Display the "Standard Deviation" of ALL or any PART of the Array', NL, \
                               '4) Calculate the Square Root of a Real number', NL, \
                               '5) Quit', NL, NL, 0

        Prompt1    BYTE NL,    'Type a number to select --> ', 0
        Prompt2    BYTE NL,    'Enter the starting array index --> ', 0
        Prompt3    BYTE NL,    'Enter the number of elements to process --> ', 0
        Prompt4    BYTE NL,    'Enter the number the square root of --> ', 0
        Output1    BYTE        'The selected elements are: ', 0
        Output2    BYTE        'The Mean for the selected elements is: ', 0
        Output3    BYTE        'The Standard Deviation for the selected elements is: ', 0
        Output4    BYTE NL,NL, 'The Square Root of the number is: ', 0   

        Error1     BYTE        'Cannot compute mean and standard deviation with less than two elements!', 0
        Error2     BYTE NL,    'You cannot take the square root of negative number!',NL, NL, 0
        Error3     BYTE NL,    'That is not a valid menu selection. Try again.', 0
        Error4     BYTE        'That is not a valid array index.', NL, \
                               'Seleect 0 through 93.', 0
        Error5     BYTE        'That is not a valid number of elements. Try again.', 0
        Error6     BYTE        'That is not a valid number for a square root. Try again.', 0

        newLine    BYTE NL,    0
    InString   BYTE        MAXSTR dup(0)
    OutString  BYTE        MAXSTR dup(0)
    MaxIntStr  BYTE        NL,LF,'Max Int for 64 bits is -> ',0
    MaxInt    QWORD       0FFFFffffFFFFffffh ;18446744073709551615d
    InKey    BYTE        0
    BoolFlag   BYTE        FALSE
    UsrSelect  BYTE        0
    StartIndex BYTE        0
    StIdx      QWORD       0
    NumElement BYTE        0
    NumElmt    QWORD       0
        UsrNumSR   QWORD       0
        UsrSqRt    REAL8       0.0
        TestInMean BYTE       0
        TestMean   REAL8       0.0   
    Tempo      REAL8       0.0
        MeanSum    REAL8       0.0
        Test2      BYTE        0
        Test3      QWORD       0
        Test4      BYTE        0
        FibArray   QWORD       94 DUP(?)
        TestArray  QWORD       1, 2, 3, 4, 5 DUP(?)
.CODE
main PROC
sub  rsp, 28h ;reserve stack space for five (5) qwords
        lea  rsi,Intro ;point to the Intro string
        call PrintStr ;  and print it
        call calculateFibonacci     ;call calculateFibonacci procedure
        call DisplayMenu            ;display the menu
        add  rsp, 28h ;restore stack space
        call ExitProcess ;exit to operating system
main ENDP

;--------------------- Procedure to display Menu ---------------------------------
; Requires : Nothing
; Process  : Displays Menu & calls appropriate protocols
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

DisplayMenu PROC USES rax rcx rdx r8 r9 r10 r11
        sub  rsp, 28h           ;save volitile registers
        call clearRegs
@@Start:lea  rsi, Menu          ;point to Menu
        call PrintStr           ;print the string
@@Input:lea  rsi, Prompt1       ;point to Prompt1
        call PrintStr           ;print the string
        lea  rsi, UsrSelect     ;point to UsrSelect
        call GetChar            ;get the character
        cmp  UsrSelect, 31h     ;compare UsrSelect with 31h
        jb   @@Err              ; if below, jump to @@Err
        je   @@User1            ; if even, @@User1
        cmp  UsrSelect, 32h     ;compare UsrSelect, 32h
        je   @@User2            ; if even, @@User2
        cmp  UsrSelect, 33h     ;compare UsrSelect, 33h
        je   @@User3            ; if even, @@User3
        cmp  UsrSelect, 34h     ;compare UsrSelect, 34h
        je   @@User4            ; if even, @@User4
        cmp  UsrSelect, 35h     ;compare UsrSelect, 35h
        je   @@Done             ; if even, @@Done
        jmp  @@Err              ;jump to @@Err
@@User1:call printFibonacci     ;call printFibonacci procedure
        jmp  @@Start            ;jump to @@Start
@@User2:call calculateMean      ;call calculateMean procedure
        jmp  @@Start            ;jump to @@Start
@@User3:call standardDeviation  ;call standardDeviation procedure
        jmp  @@Start            ;jump to @@Start
@@User4:call squareRoot         ;call squareRoot procedure
        jmp  @@Start            ;jump to @@Start
@@Err:  lea  rsi, Error3        ;point to Error3
        call PrintStr           ;print the string
        jmp  @@Input            ;jump to @@Input
@@Done: add  rsp, 28h           ;restore volitile registers
        ret                     ;return to calling procedure
DisplayMenu ENDP

;----------------- Procedure to calculate the Fibonacci sequence -----------------
; Requires : Nothing
; Process  : Calculates the first 94 Fibonacci numbers. Stored in an array.
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

;*********************************************************************************************
;CALCULATE FIBONACCI SEQUENCE TESTED AND WORKING
;*********************************************************************************************

calculateFibonacci PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h           ;save contents of volitile registers
        lea  rcx, FibArray      ;get address of first array element
        mov  rsi, rcx           ;copy rcx to rsi
        mov  rdx, 92d           ;copy 92d into rdx (counter)
        mov  rcx, rdx           ;copy contents of rdx into rcx
        mov  rbx, 0d            ;copy 0d into rbx
        mov  [rsi], rbx         ;copy 0d into array element 0
        mov  r10, 0d            ;copy 0d into r10 register
        add  rsi, 8             ;get address of next array element
        mov  rbx, 1d            ;copy 1d into rbx
        mov  [rsi], rbx         ;copy contents of rbx into array element
        mov  r11, 1d            ;copy 1d into r11 register
@@Start:add  rsi, 8             ;get address of next array element
        add  r10, r11           ;add r10 and r11 register, new value in r10
        mov  [rsi], r10         ;copy new value into next array element
        sub  rsi, 8             ;get address of previous array element
        mov  r11, [rsi]         ;copy value in previous array element to r11
        add  rsi, 8             ;get address of next array element
        loop @@Start            ;loop to start until rcx == 0
@@Done: add  rsp, 28h           ;restore volitile registers
        ret                     ;return to calling procedure
calculateFibonacci ENDP

;------------------- Procedure to clear all registers ----------------------------
; Requires : Nothing
; Process  : Clears all registers via the xor command
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

clearRegs PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h
        xor  rax, rax
        xor  rbx, rbx
        xor  rcx, rcx
        xor  rdx, rdx
        xor  r8, r8
        xor  r9, r9
        xor  r10, r10
        xor  r11, r11
        xor  rsi, rsi
        xor  rdi, rdi
        add  rsp, 28h
        ret
clearRegs ENDP

;------------------- Procedure to Print the Fibonacci sequence -------------------
; Requires : Nothing
; Process  : Prints the first 94 Fibonacci numbers. Stored in an array.
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

;*******************************************************************************************
;PRINT FIBONACCI SEQUENCE WORKS 1st RUN THROUGH, BREAKS ON ZERO ELEMENT AFTER THAT
;*******************************************************************************************

printFibonacci PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h                   ;save contents of volitile registers

@@Pro1: lea  rsi, Prompt2               ;Prompt user for starting index
        call PrintStr                   ;print the string
        lea  rsi, StartIndex            ;point to StartIndex
        call ReadStr                    ;ReadString
        lea  rsi, StartIndex            ;point to StartIndex
        lea  rdi, StIdx                 ;point to StIdx
        call Ascii2Qword                ;convert from Ascii to Qword
        cmp  StIdx, 0d                  ;compare StartIndex with '0'
        jb   @@Err1                     ; if below, jump to @@Err1

@@Pro2: lea  rsi, Prompt3               ;Prompt the user for number of elements to process
        call PrintStr                   ;print the string
        lea  rsi, NumElement            ;storage location for number of elements
        call ReadStr                    ;read string of user input
        lea  rsi, NumElement            ;point to NumElement   
        lea  rdi, NumElmt               ;point to NumElmt
        call Ascii2Qword                ;convert from Ascii2Qword
        cmp  NumElmt, 1d                ;compare NumElement with '1'
        jb   @@Err2                     ; if below, jump to @@Err2
        mov  rdx, OFFSET FibArray       ;copy OFFSET FibArray to rdx
        mov  rcx, StIdx                 ;copy StIdx to rcx
        cmp  StIdx, 0d                  ;comare rcx to 0d
        je   @@Skip                     ; if even, jump to @@Skip

@@SIdx: add  rdx, 8                     ;get address of next array element
        loop @@SIdx                     ;loop to @@SIdx

@@Skip: mov  rcx, NumElmt               ;copy NumElmt to rcx

@@Start:lea  rsi, [rdx]                 ;point to next element in array
        lea  rdi, Test2                 ;point to Test2
        call Qword2Ascii                ;convert Qword 2 Ascii character
        lea  rsi, Test2                 ;point to Test2
        call PrintStr                   ;print the string
        add  rdx, 8                     ;get address of next array element
        lea  rsi, newLine               ;point to newLine
        call PrintStr                   ;print the string
        loop @@Start                    ;loop to @@Start
        jmp  @@Done                     ;jump to @@Done

@@Err1: lea  rsi, Error4                ;point to Error4
        call PrintStr                   ;print the string
        jmp  @@Pro1                     ;jump to @@Pro1

@@Err2: lea  rsi, Error5                ;point to Error5
        call PrintStr                   ;print the string
        jmp  @@Pro2                     ;jump to @@Pro2

@@Done: add  rsp, 28h                   ;restore volitile registers
        ret                             ;return to calling procedure
printFibonacci ENDP

;---------------------- Procedure to Calculate Square Root -----------------------
; Requires : Nothing
; Process  : Calculates the Square Root of a Number
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

;***********************************************************************************
;SQUARE ROOT PROCEDURE TESTED AND FULLY FUNCTIONING
;***********************************************************************************

squareRoot PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h               ;restore volitile registers
        call clearRegs              ;call procedure to clear all registers
@@Start:lea  rsi, Prompt4           ;point to Prompt4
        call PrintStr               ;print the string
        lea  rsi, UsrNumSR          ;point to UsrNumSR
        call ReadStr                ;read the string frme user input
        lea  rsi, UsrNumSR          ;point to UsrNumSR 
        lea  rdi, UsrSqRt           ;point to UsrSqRt
        call Ascii2Real             ;convert Ascii to FPU digit
        cmp  UsrSqRt, 30h           ;compare UsrSqRt with 30h
        jbe  @@Error                ; if below or even, jump to @@Error
        finit                       ;initialize fpu
        fld  UsrSqRt                ;push real value onto top of stack
        fsqrt                       ;replace value on top of stack with its sqare root
        fstp UsrSqRt                ;pop top of stack off into UsrSqRt
        lea  rsi, UsrSqrt           ;point to UsrSqRt
        lea  rdi, UsrNumSR          ;point to UsrNumSR
        call Real2Ascii             ;convert Real to Ascii
        lea  rsi, Output4           ;point to Output4
        call PrintStr               ;print the string
        lea  rsi, UsrNumSR          ;point to UsrNumSR
        call PrintStr               ;print the string
        jmp  @@Done                 ;jump to @@Done
@@Error:lea  esi, Error2            ;point to Error2
        call PrintStr               ;print the string
        jmp  @@Start                ;jump to @@Start   
@@Done: add  rsp, 28h               ;restore volitile registers
        ret                         ;return to calling procedure
squareRoot ENDP

;---------------------- Procedure to Calculate Mean  ======-----------------------
; Requires : Nothing
; Process  : Calculates the Mean of a range of numbers
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

;*******************************************************************************************
;CALCULATE MEAN PROCEDURE UNTESTED AND STILL NEEDS MODIFICATION
;*******************************************************************************************

calculateMean PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h                   ;reserve stack space
        call clearRegs                  ;call procedure to clear all registers
        finit

@@Pro1: lea  rsi, Prompt2               ;Prompt user for starting index
        call PrintStr                   ;print the string
        lea  rsi, StartIndex            ;point to StartIndex
        call ReadStr                    ;ReadString
        lea  rsi, StartIndex            ;point to StartIndex
        lea  rdi, StIdx                 ;point to StIdx
        call Ascii2Qword                ;convert from Ascii to Qword
        cmp  StIdx, 0d
        jb   @@Err1

@@Pro2: lea  rsi, Prompt3               ;Prompt the user for number of elements to process
        call PrintStr                   ;print the string
        lea  rsi, NumElement            ;storage location for number of elements
        call ReadStr                    ;read string of user input
        lea  rsi, NumElement            ;point to NumElement   
        lea  rdi, NumElmt               ;point to NumElmt
        call Ascii2Qword                ;convert from Ascii2Qword
        cmp  NumElmt, 2d
        jb   @@Err2
        mov  rdx, OFFSET FibArray       ;copy OFFSET FibArray to rdx
        mov  rcx, StIdx                 ;copy StIdx to rcx
        cmp  StIdx, 0d
        je   @@Skip
        mov  rax, 0d

@@SIdx: add  rdx, 8                     ;get address of next array element
        loop @@SIdx                     ;loop to @@SIdx

@@Skip: mov  rcx, NumElmt               ;copy NumElmt to rcx

@@Start:add rax, [rdx]
        add rdx, 8
        loop @@Start

        mov Test3, rax
        lea rsi, Test3
        lea rdi, Test4
        call Qword2Ascii
        lea rsi, Test4
        lea rdi, Tempo
        call Ascii2Real
       
        xor  rbx, rbx
        mov  rbx, NumElmt
        ;mov  MeanSum, rax
        fld  Tempo
        fld  NumElmt
        fdiv
        fstp TestMean
        lea  rsi, TestMean
        lea  rdi, TestInMean
        call Real2Ascii
        lea  rsi, TestInMean
        call PrintStr
        jmp  @@Done

@@Err1: lea  rsi, Error4
        call PrintStr
        jmp  @@Pro1

@@Err2: lea  rsi, Error5
        call PrintStr
        jmp  @@Pro2

@@Done: add  rsp, 28h
        ret
calculateMean ENDP

;-------------------- Procedure to Calculate Std Deviation -----------------------
; Requires : Nothing
; Process  : Calculates the Standard Deviation of a range of numbers.
;          : All volitile registers are preserved.
; Return   : Nothing
;---------------------------------------------------------------------------------

;******************************************************************************************
;WTF????
;******************************************************************************************

standardDeviation PROC USES rax rbx rcx rdx r8 r9 r10 r11
        sub  rsp, 28h
        call clearRegs
@@Start:lea  rsi, Prompt2
        call PrintStr
        lea  rsi, StartIndex
        call ReadStr
        cmp  StartIndex, 0d
        jb   @@Err1
        lea  rsi, Prompt3
        call PrintStr
        lea  rsi, NumElement
        call ReadStr
        lea  rsi, NumElement
        lea  rdi, NumElement
        cmp  NumElement, 1d
        jb   @@Err2
        mov  rax, 30h
        ;mov  rcx, StartIndex
@@Loop:
        ;calculate the mean (average) of all the values in the list
            ;begin at StartIndex
            ;go NumElement number of elements
            ;sum them up
            ;divid
            ;by NumElement
        ;for each number in the list, calculate (value - mean)^2
            ;begin at StartIndex
            ;value at start index - mean
            ;square value
            ;go through list until last number has been calculated
        ;calculate the variance by taking the average of all those squared values
            ;take value and divide by NumElement
        ;to obtain the standard deviation, take the square root of the variance
            ;take value and square root
            ;print the new resulting value
            ;this value is the std. deviation
@@Err1: lea  rsi, Error4
        call PrintStr
        jmp  @@Start
@@Err2: lea  rsi, Error5
        call PrintStr
        jmp  @@Start
@@Done: add  rsp, 28h
        ret
standardDeviation ENDP
END ;End of the code segment

qWord

for calcuating the sqare root:
; rax = value = __int64
cvtsi2sd xmm0,rax
sqrtsd xmm0,xmm0
cvttsd2si rax,xmm0
; rax = (__int64) sqrt((double) value)
FPU in a trice: SmplMath
It's that simple!