汇编:Lab09_Task03.exe中在0x9999999A处引发的异常:0xC0000005:执行位置0x9999999A的访问冲突

我写了一些汇编代码来执行一些文本文件IO。该代码可以正常工作并提供正确的输出。问题是执行代码后,显示错误消息:

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

我使用的是Visual Studio 2019,但我尝试调试代码,但错误在ret语句之后出现。

.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",0
outputFormat1 byte "The average is %.2f",0
outputFormat2 byte "The frequency of grades above average is %d",0
outputFormat3 byte "The frequency of grades equal to the average is %d",0
outputFormat4 byte "The frequency of grades below average is %d",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
pqlay 回答:汇编:Lab09_Task03.exe中在0x9999999A处引发的异常:0xC0000005:执行位置0x9999999A的访问冲突

您在这个位置上有两个位置:

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

在任何情况下,您都不会还原堆栈指针。在函数结束时,执行ret指令时,它不会返回到调用方,而是返回到基于您存储在堆栈中的最后一个值的某个值。您需要平衡所有从esp减去的减数,以使该函数末尾的esp的值与输入该函数时的值相同。

(顶部附近的movsd xmm0,real8 ptr [esp]指令也是错误的,因为部分加载的数据将是返回地址。)

本文链接:https://www.f2er.com/3156853.html

大家都在问