2013-10-25 63 views
1

我想在32位x86 AT & T彙編中編寫一個簡單的類蛇遊戲,並且我遇到了一個奇怪的問題。我有一些C函數用於某些任務,例如使用ncurses打印到屏幕上。這種特殊的功能,snake_print,看起來是這樣的:使用32位x86 AT&T彙編調用C函數的問題

snake_print(int x, int y, int ch){ 
    mvprintw(y,x,"%c",ch); 
    wrefresh(screen); 
} 

其中put_char投放在屏幕上的字符chrefresh_scr刷新它。變量screen是全球性的。

所以,調用這個我把一些值在棧中,像這樣的:

subl $12,%esp 
pushl $'o' 
pushl $15 
pushl $15 
call snake_print 
addl $12,%esp 

當我看從snake_print函數的棧GDB,它看起來它應該。它向下移動到應該從具有正確堆棧內容的函數返回的地方,然後發生某些事情;當GDB工作人員}snake_print作爲代碼運行時,值0x804d190被放在堆棧上,同時調用snake_print(0x804d190,15,111)。執行的下一行代碼是refresh_scr(scr),然後出現分段錯誤。

我用0123檢查0x804d190與GDB,並看到它包含值0x10000f。因爲在新的呼叫snake_print,15我以前的x值的0x804d190交換,它似乎有事情發生到被存儲的X值的內存地址,因爲15 = 0xf和我們「只一個「,可以這麼說。

我不知道爲什麼發生這種情況,所以我想知道是否有人可以幫忙弄清楚什麼是錯的?

回答

3

你在混合兩種傳遞參數的方法。因爲subl推動改變堆棧,addl是不夠的重新平衡它,所以你的程序後來崩潰。用推和恢復通話後堆棧

1):

您應該使用一個或另一個。

pushl $'o' 
pushl $15 
pushl $15 
call snake_print 
addl $12,%esp 
<...> 
pushl $'p' 
pushl $12 
pushl $12 
call snake_print 
addl $12,%esp 

2)分配一次堆棧並使用movs來設置參數。

subl $12,%esp 
<...> 
movl $'o', 8(%esp) 
movl $15, 4(%esp) 
movl $15, 0(%esp) 
call snake_print 
<...> 
movl $'p', 8(%esp) 
movl $12, 4(%esp) 
movl $12, 0(%esp) 
call snake_print 
<...> 
addl $12,%esp 
+0

這有助於很多,謝謝! – Psyberion