c - Sleep() 内联汇编调用可以工作,但会生成运行时检查失败

标签 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 :

}

}

最佳答案

WinApi Sleep()函数遵循 STDCALL calling convention 。当它返回时,它已经清理了堆栈。当您执行相同操作时,堆栈将被“过度清理”;-)。删除该行:

    pop eax                //cleans the stack

不知道你用的是什么编译器。我的编译器 (Visual Studio 2010) 需要再次调用 Sleep() :

call dword ptr [Sleep]

关于c - Sleep() 内联汇编调用可以工作,但会生成运行时检查失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34455786/

相关文章:

c - 当一切都可以通过寄存器完成时,为什么要减少 %rsp 呢?

assembly - CPUID:为什么某些功能必须将 MISC_ENABLE.LCMV 设置为 0?可以暂时覆盖吗?

c++ - 混合 C/C++ 源,无法识别链接上的 'extern' 变量

c - 使用 GDB 找出我的程序在哪里挂起?

c++ - 标签地址 (MSVC)

c - 堆栈上的本地存储

c - C程序的堆栈会缩小吗?

c - 在 c 的 if 语句中声明变量是个坏习惯吗?

将鼠标位置转换为世界位置 OpenGL

c - XLib: 'Soft-Closing' 一个窗口