Sleep()内联汇编调用有效但生成运行时检查失败

时间:2015-12-24 16:57:03

标签: c assembly stack sleep inline-assembly

正如我的问题的标题所说,sleep()函数正常工作(以及C函数中的所有其他函数调用,问题是在它运行完毕后我得到一个错误,上面写着:

“运行时检查失败#0 - ESP的值未在函数调用中正确保存。这通常是调用使用一个调用约定声明的函数,其中函数指针使用不同的调用约定声明。 “

我相信当我调用sleep函数时我正在处理寄存器的方式是正确完成的,因为它实际上有效,我发布了整个函数以防万一需要检测我可能在另一个函数中错误放置堆栈内容的位置调用

该功能基本上可以打印从底部最后一层到最顶层的电梯。

 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 :

}

}

2 个答案:

答案 0 :(得分:0)

评论太多了。我的意思是推送和弹出您感兴趣保留的寄存器,包括那些您从esi <-> ebxedi <-> 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

答案 1 :(得分:0)

WinApi Sleep()函数跟在STDCALL calling convention之后。它返回时已经清理了堆栈。当你这样做时,堆栈是'#34; overcleaned&#34; ;-)。删除行:

    pop eax                //cleans the stack

我不知道您使用的编译器。我的编译器(Visual Studio 2010)需要另一次调用Sleep()

call dword ptr [Sleep]