2012-02-09 190 views
0

我正在閱讀一本C語言書,它很多內容都與asm有關,並且正在用GDB來查看寄存器和內存。 問題是,當我編譯和反彙編完全相同的源文件(實際上使用cd書附帶的源文件)時,彙編指令看起來與本書中的內容有很大不同。 這本書使用英特爾風味的大會,我把「集拆卸英特爾」在gdb,所以它不是..只是說明是在不同的順序,有些都在一起不同,還有一些其他的怪癖。gdb的奇怪結果

例如,在該書中有EIP寄存器MOV指令:對應於初始化變量i爲0,在for循環中

(gdb) x/i $eip 
mov DWORD PTR[ebp-4], 0x0 

(I = 0,I < 10,I ++ )

然而,在我的GDB控制檯,與在同一個地方斷點(設置打破爲主;運行)我看到這一點:

(gdb) x/i $eip 
mov DWORD PTR[esp+0x1c], 0x0 

察覺到它的引用不同的瑞吉如果我檢查esp的值,它本身就是0x1c,而不是ebp 。但是,如果我嘗試檢查0x1c或者esp + 0x1c處的內容,它告訴我我無法查看這些地址

因此,隨着本書的繼續,我無法遵循,因爲它開始跟蹤ebp,ebp-4等內容的蹤跡,並且在我的asm中,ebp寄存器似乎沒有任何事情發生。該書寫於2008年,所以我不能想象它如此過時以至於gcc或gdb的版本更改會引入顯着的更改(或者做到了這一點?)......是否有可能存在一些編譯器優化或默認情況下打開的某些內容會產生這樣的不同結果?

在此先感謝

編輯:奇怪。我嘗試了每個建議,但沒有成功。然後我做了a.out並重新編譯爲新的,現在它工作正常(指令與本書不同,但我可以查看與本書相對應的地址;只要我可以遵循相應的模式,一切都很好,不必是完全相同的asm,這隻會讓它太容易!) 再次感謝您的所有幫助和建議。

回答

0

這將是非常平臺和編譯器特定的。恐怕沒有什麼可以做的了。

+0

謝謝。本書使用的是32位英特爾版本,我都是用gcc編譯的(我需要檢查版本並更新qeustion),運行linux。本書基於Ubuntu(同樣需要檢查版本),我正在運行最新的Arch安裝。 我會假設與相同的體系結構和相同的編譯器(gcc)的機器代碼將是相同的沒有? 無論哪種方式,我覺得奇怪的是,一個值正在被初始化到我無法檢查的地址,也奇怪它被$ esp引用,即堆棧指針... – speakingcode 2012-02-09 05:11:06

+1

不,沒有理由它應該是相同的。你可以用'-O0'或'-march = i386'來玩。但這完全不同,這並不奇怪。 – 2012-02-09 05:14:01

1

有一百萬件事情可能導致這種情況。如果你在不同的體系結構上編譯你的代碼,我期望這樣做(並且不,這並不一定意味着32位和64位 - 實際上,任何不同的CPU體系結構都可以改變執行順序,我將會解釋) 。如果您通過優化來編譯程序,它將改變執行順序以最好地利用CPU的管道。這可能意味着添加一些NOOP指令,或者完全重新排序(當然是在合理範圍內)。另外一些CPU有多種處理方式,一種方式通常比另一種處理速度快(intel LOOP指令出現在腦海中 - 現代編譯器避免像鼠疫這樣的指令,因爲它很糟糕)。如果一個寄存器比另一個更有效,它將使用它。

故事的寓意:出於學習的目的,作者和讀者都需要禁用所有優化。另外爲了增加積分:使用相同版本的gcc和相同的平臺。

+0

感謝您的洞察力。這就是我想知道的,我怎麼能不強制優化。我明白,確切的內存地址,甚至指令可能因體系結構而異,這是編譯器的重點,但我只是感到驚訝,它有很大的不同 - 即使在asm似乎是一個不同的程序(它是一起的沒有什麼,但一個for循環主要是非常簡單的遵循) 真的,雖然問題是說價值初始化在我無法檢查(esp + 0x1c),不應該是這樣的地址 – speakingcode 2012-02-09 07:21:02

+0

@rootlicker 'gcc -O0'(這是字母O後跟數字0) – 2012-02-09 15:09:07

1

它看起來像你編譯的代碼編譯爲-fomit-frame-pointers,這成爲GCC-4.6的默認值。

嘗試用明確的-fno-omit-frame-pointer構建。我希望結果會更接近這本書。