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
.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
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.
movsd xmm0, real8 ptr [esp] instruction near the top is also wrong, since part of the data loaded will be the return address.)
User contributions licensed under CC BY-SA 3.0