Sleep() inline assembly call works but generates runtime check-failure

强颜欢笑 提交于 2019-12-12 01:36:44

问题


As the title of my question says the sleep() function works properly (and every other function call in the C function, the problem is that after it's finished running I get an error that says:

"Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."

I believe the way I'm handling the registers when I call the sleep function is done properly because it actually works, I posted the whole function just in case it's needed to detect where I might be misplacing the stack contents in another function call.

The function basically prints an elevator going up from the last floor on the bottom to the top-most one.

 int deSubidaASM() {

int  sleepTime = 900;          
char *clear = "cls";
char *piso = "[x]";
char *pisoVacio = "[ ]";
char *texto = "%s\n";
char *fuerza = "Fuerza G: 1";


_asm {

        mov ebx, 0             //int a=0
        mov ecx, 9             //int b=9

        _while1:               //while (a <= 9)
        cmp ebx, 9             //
        jg _fin               //if ebx>9, end

        _Fuerza:          //writes on screen
        mov eax, fuerza
        push eax
        mov eax, texto
        push eax
        mov esi, ecx   //
        call printf
        mov ecx, esi   //
        pop edx
        pop edx     

        _sleep:
        mov eax, sleepTime
        push eax               //pushes the sleep time input
        mov esi, ebx         //auxiliary variable to keep the cycle counters
        mov edi, ecx           //same as the above line comment
        call Sleep             //sleep()  call
        mov ecx, edi           //returns the values from the aux variables
        mov ebx, esi           //same as the above line comment
        pop eax                //cleans the stack


        _clearscreen:
         mov eax, clear         //Bloque para clearscreen
         push eax
         mov esi, ebx
         mov edi, ecx
         call system
         mov ecx, edi
         mov ebx, esi
         pop edx


        _while2 :                //while (b >= 0) 
        cmp ecx, 0              //
        jle _resetearWhile2     //if ecx<0 restart while2       


        cmp ebx, ecx             // if the levels match 
        je _printPiso           //print elevator
        jne _printVacio         //print floor


        _printPiso :
        mov eax, piso
        push eax
        mov eax, texto
        push eax
        mov esi, ecx   //
        call printf
        mov ecx, esi   //
        pop edx
        pop edx
        dec ecx
        jmp _while2

        _printVacio :
        mov eax, pisoVacio
        push eax
        mov eax, texto
        push eax
        mov esi, ecx       //
        call printf
        mov ecx, esi       //
        pop edx
        pop edx
        dec ecx
        jmp _while2


        _resetearWhile2:
        mov ecx, 9              //b=9
        inc ebx            
        jmp _while1            


        _fin :

}

}


回答1:


The WinApi Sleep() function follows the STDCALL calling convention. It had already cleaned up the stack when it returns. When you do the same, the stack is "overcleaned" ;-). Remove the line:

    pop eax                //cleans the stack

I don't know what compiler you use. My compiler (Visual Studio 2010) needs another call to Sleep():

call dword ptr [Sleep]



回答2:


Too much for a comment. I mean push and pop the registers you are interested in preserving, including those you are juggling around from esi <-> ebx and edi <-> ecx.

_sleep:
push    ecx                 // save the regs
push    edx
push    ebp

mov     eax, sleepTime      // func argument
push    eax                 // pushes the sleep time input
call    Sleep               // sleep() call
pop     eax                 // clean off stack

pop     ebp                 // restore regs
pop     edx
pop     ecx


来源:https://stackoverflow.com/questions/34455786/sleep-inline-assembly-call-works-but-generates-runtime-check-failure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!