Assembly: Exception thrown at 0x9999999A in Lab09_Task03.exe: 0xC0000005: Access violation executing location 0x9999999A

0

I wrote some assembly code that does some text Files IO. The code works correctly and gives the correct output. The problem is after executing the code there is an error displayed says:

Exception thrown at 0x9999999A in Lab09_Task03.exe: 0xC0000005: Access violation executing location 0x9999999A.

I'm using Visual Studio 2019 and I tried to debug the code but the error comes right after the ret statement.

.686
.model flat,c
.xmm

includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib 

extern fopen_s:proc, fscanf_s:proc, exit:proc,
    printf_s:proc, rewind:proc,fclose:proc
.data
sumGrades real8 0.0
countGrades dword 0
countAboveAverage dword 0
countAverage dword 0
countBelowAverage dword 0

readingMode byte "r",0
fileName byte "grades.txt",0
errorMsg byte "Error in opening grades.txt",13,10,0
doubleFormat byte "%lf",0
fileEmptyError byte "Error: The input file is empty",13,10,0
outputFormat1 byte "The average is %.2f",13,10,0
outputFormat2 byte "The frequency of grades above average is %d",13,10,0
outputFormat3 byte "The frequency of grades equal to the average is %d", 13,10,0
outputFormat4 byte "The frequency of grades below average is %d", 13,10,0

.data?
inFilePtr dword ? ;File pointer
errorNum dword ?
grade real8 ?
average real8 ?

.code
main proc
push offset readingMode     ; reading a file
push offset fileName        ;
push offset inFilePtr       ;
call fopen_s                ;
add esp,12                  ;
mov errorNum, eax           ; checking if there is a file with the name "grades.txt"
cmp eax , 0                 ;
je noerror                  ;
push offset errorMsg        ;
call printf_s               ;
add esp,4                   ;
                            ;
push 1                      ;
call exit                   ; exit if there is no such file

noerror:
StartLoop:                  ; reading grades and finding the sumGrades
    push offset grade       ;
    push offset doubleFormat;
    push inFilePtr          ;
    call fscanf_s           ;
    add esp,12              ;
                            ;
    cmp eax , 0FFFFFFFFH    ; check if eax == EOF (end of file) character
    je endLoop              ;

    movsd xmm0, real8 ptr [esp] ;
    inc countGrades             ;
    addsd xmm0 , grade          ;
    sub esp,8                   ;
    movsd real8 ptr [esp], xmm0 ;
    jmp StartLoop               ;
endLoop:                    ;
movsd xmm0, real8 ptr [esp] ;
movsd sumGrades, xmm0       ;
cmp countGrades, 0          ; check if there is any grades or none
    jne noFileEmptyError    ;

    push offset fileEmptyError  ; if the file has no grades print error message
    call printf_s               ;
    add esp,4                   ;

    jmp endOfProgram

noFileEmptyError:               ; else 
    movsd xmm0, sumGrades       ; find the average
    cvtsi2sd xmm1, countGrades  ;
    divsd xmm0, xmm1            ;
    movsd average, xmm0         ;

    push inFilePtr              ; move the file pointer to the beginning of the file
    call rewind                 ;
    add esp,4                   ;

    start_Loop:                 ; find the frequency of the grades that is ( > || < || = )
        push offset grade       ; reading grades from "grades.txt" file
        push offset doubleFormat;
        push inFilePtr          ;
        call fscanf_s           ;
        add esp, 12             ;

        cmp eax, 0ffffffffH     ; if eax == EOF
        je end_Loop             ;

        movsd xmm0, grade       ;   comparing the grades to the average to determine
        movsd xmm1, average     ;   whether a grade is above, below or equal to the average
        ucomisd xmm0,xmm1       ;
            jne notEqual        ;
            inc countAverage    ;   increment number of grades that is equal to the average
            jmp start_Loop      ;   
        notEqual:               ;
        ucomisd xmm0, xmm1      ;
            jna notGreater      ;
            inc countAboveAverage;  increment number of grades that is above the average
            jmp start_Loop      ;
        notGreater:             ;
            inc countBelowAverage;  increment number of grades that is below the average
            jmp start_Loop      ;
    end_Loop:   

    movsd xmm0, average         ;   display the results: average, number of grades that is above the average,
    sub esp,8                   ;                       number of grades that is equal to the average and
    movsd real8 ptr [esp], xmm0 ;                       number of grades that is below the average  
    push offset outputFormat1   ;
    call printf_s               ;
    add esp,12                  ;

    push countAboveAverage      ;
    push offset outputFormat2   ;
    call printf_s               ;
    add esp,8                   ;

    push countAverage           ;
    push offset outputFormat3   ;
    call printf_s               ;
    add esp,8                   ;

    push countBelowAverage      ;
    push offset outputFormat4   ;
    call printf_s               ;
    add esp,8                   ;
endOfProgram:                   ;
    push inFilePtr              ; closing the file
    call fclose                 ;
    add esp, 4                  ;
ret
main endp
end
assembly
x86
masm
asked on Stack Overflow Nov 5, 2019 by ahmed alzahrani • edited Nov 5, 2019 by 1201ProgramAlarm

1 Answer

3

You have two places with this sequence:

sub esp,8
movsd real8 ptr [esp], xmm0

In neither instance do you ever restore the stack pointer. At the end of your function, when the ret instruction executes, it will not return to the caller but to some value based on the last value you stored on the stack. You need to balance all the subtractions from esp with additions, so that the value of esp at the end of the function is the same as when the function was entered.

(The movsd xmm0, real8 ptr [esp] instruction near the top is also wrong, since part of the data loaded will be the return address.)

answered on Stack Overflow Nov 5, 2019 by 1201ProgramAlarm

User contributions licensed under CC BY-SA 3.0