2015-12-24 45 views
0

由於我的問題的標題說sleep()函數正常工作(和C函數中的每個其他函數調用,問題是它完成運行後I得到的錯誤如下:睡眠()內聯彙編調用的作品,但會產生運行時檢查失敗

「運行時檢查失敗#0 - ESP的值未正確保存在函數調用中,這通常是調用一個函數指針調用約定的函數的結果「

我相信我在調用睡眠函數時處理寄存器的方式是正確完成的,因爲它實際上起作用了,我發佈了整個函數以防萬一需要在另一個函數調用中檢測我可能在哪裏放置棧內容。

該功能基本上打印從底部最後一層到最頂層的電梯。

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 : 

} 

}

+0

你爲什麼不只是推動和彈出你想保持寄存器(和ESP作爲錯誤消息建議) ? –

+0

@WeatherVane:你是說我應該在函數調用之前將ESP寄存器中的內容推入另一個函數,然後在函數調用之後將其返回以保留它的內容?我試過,我得到另一個錯誤「訪問衝突讀取位置0x00000000」。 – atf01

回答

0

WinApi Sleep()函數遵循STDCALL calling convention。它在返回時已經清理了堆棧。當你這樣做時,堆棧「被徹底清理」;-)。刪除線:

pop eax    //cleans the stack 

我不知道你用什麼編譯器。我的編譯器(Visual Studio 2010中)需要另一個調用Sleep():而不是嘗試其他寄存器之間變戲法

call dword ptr [Sleep] 
+0

非常感謝,你說得對,它現在起作用了!在VS2015呼叫睡眠使用 '調用睡眠' 工作得很好,我使用的呼叫方法之前,在這裏的另一名成員指出。 – atf01

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 
+0

嘗試了這個(推動ecx和edx寄存器,這是我有興趣保存的寄存器),沒有工作,仍然得到相同的錯誤。 – atf01

+0

你爲什麼不推'ebp'?是的,對不起,我錯誤地得到了其他regs。糾正。 –

+0

我也推ebp抱歉,我沒有指定,但仍然無法正常工作。 – atf01