Sleep() 内联汇编调用有效但生成运行时 check-failure
Sleep() inline assembly call works but generates runtime check-failure
正如我的问题标题所说,sleep() 函数正常工作(以及 C 函数中的所有其他函数调用,问题是在它完成后 运行 我收到一条错误消息:
"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."
我相信我在调用睡眠函数时处理寄存器的方式是正确的,因为它确实有效,我发布了整个函数以防万一需要它来检测我可能错放堆栈内容的位置另一个函数调用。
该函数主要是打印一部电梯从底部的最后一层到 top-most 层。
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 :
}
}
评论太多了。我的意思是压入和弹出您有兴趣保留的寄存器,包括您在 esi <-> ebx
和 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
WinApi Sleep() function follows the STDCALL calling convention。它在 returns 时已经清理了堆栈。当您执行相同操作时,堆栈为 "overcleaned" ;-)。删除行:
pop eax //cleans the stack
不知道你用的是什么编译器。我的编译器 (Visual Studio 2010) 需要再次调用 Sleep():
call dword ptr [Sleep]
正如我的问题标题所说,sleep() 函数正常工作(以及 C 函数中的所有其他函数调用,问题是在它完成后 运行 我收到一条错误消息:
"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."
我相信我在调用睡眠函数时处理寄存器的方式是正确的,因为它确实有效,我发布了整个函数以防万一需要它来检测我可能错放堆栈内容的位置另一个函数调用。
该函数主要是打印一部电梯从底部的最后一层到 top-most 层。
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 :
}
}
评论太多了。我的意思是压入和弹出您有兴趣保留的寄存器,包括您在 esi <-> ebx
和 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
WinApi Sleep() function follows the STDCALL calling convention。它在 returns 时已经清理了堆栈。当您执行相同操作时,堆栈为 "overcleaned" ;-)。删除行:
pop eax //cleans the stack
不知道你用的是什么编译器。我的编译器 (Visual Studio 2010) 需要再次调用 Sleep():
call dword ptr [Sleep]