2009-06-11 22 views
9

我最近需要在彙編級調試程序。我沒有很多彙編程序經驗,所以我想我會編寫一些簡單的C程序並單步執行,以便在開始調試其他人員代碼之前瞭解該語言。不過,我真的不明白是什麼GCC由這兩條線(編譯-ggdb -O0):這件裝配件如何工作?

items[tail] = i; 
tail = (tail+1) % MAX_SIZE; 

其中MAX_SIZE已經#defined是5,i是一個局部變量(存儲在0x8中( %ebp),我猜)。根據廣發行,這將成爲:

0x08048394 <queue+17>: mov 0x8049634,%edx 
0x0804839a <queue+23>: mov 0x8(%ebp),%eax 
0x0804839d <queue+26>: mov %eax,0x804963c(,%edx,4) 
0x080483a4 <queue+33>: mov 0x8049634,%eax 
0x080483a9 <queue+38>: lea 0x1(%eax),%ecx 
0x080483ac <queue+41>: movl $0x66666667,-0xc(%ebp) 
0x080483b3 <queue+48>: mov -0xc(%ebp),%eax 
0x080483b6 <queue+51>: imul %ecx 
0x080483b8 <queue+53>: sar %edx 
0x080483ba <queue+55>: mov %ecx,%eax 
0x080483bc <queue+57>: sar $0x1f,%eax 
0x080483bf <queue+60>: mov %edx,%ebx 
0x080483c1 <queue+62>: sub %eax,%ebx 
0x080483c3 <queue+64>: mov %ebx,-0x8(%ebp) 
0x080483c6 <queue+67>: mov -0x8(%ebp),%eax 
0x080483c9 <queue+70>: shl $0x2,%eax 
0x080483cc <queue+73>: add -0x8(%ebp),%eax 
0x080483cf <queue+76>: mov %ecx,%edx 
0x080483d1 <queue+78>: sub %eax,%edx 
0x080483d3 <queue+80>: mov %edx,-0x8(%ebp) 
0x080483d6 <queue+83>: mov -0x8(%ebp),%ebx 
0x080483d9 <queue+86>: mov %ebx,0x804963 

由於0x804963c是項目的地址,我可以看到的C代碼的第一行是如何工作的。另外,0x8049634是尾部地址,所以我想隊列+33和隊列+38相當於%ecx = tail + 1 ...但我不知道之後會發生什麼。誰會想到一個簡單的模塊可能會很複雜?

回答

14

這是一種避免執行更昂貴的除法指令的方法。當我第一次遇到這個時,我也很難過。有趣的是,搜索用於這個技巧的魔術數字(在這種情況下爲0x66666667)通常會給出解釋這個技巧的結果。 (我當時認爲這是唯一不得不繼續的具體事情,因爲我沒有消息來源。)

快速搜索給了我這篇博文:http://blog.dkbza.org/2007/09/reverse-engineering-compiler-produced.html它在底部有一些有用的鏈接(包括間接鏈接到關於這個技巧的論文)。