2011-05-05 49 views
13

每次我做一個objdump的我總是-d看到的NOP指令(什麼也不做說明)批次的彙編代碼爲什麼GCC輸出的機器代碼有NOP指令

例如採用同一方案,:

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
    printf("Hello World!\n"); 
    printf("cos: %f\n", cos(1)); 
    return 1; 
} 

的objdump的用於exampe有2個空指令在入口點

0000000000400450 <_start>: 
400450: 31 ed     xor %ebp,%ebp 
400452: 49 89 d1    mov %rdx,%r9 
400455: 5e      pop %rsi 
400456: 48 89 e2    mov %rsp,%rdx 
400459: 48 83 e4 f0    and $0xfffffffffffffff0,%rsp 
40045d: 50      push %rax 
40045e: 54      push %rsp 
40045f: 49 c7 c0 00 06 40 00 mov $0x400600,%r8 
400466: 48 c7 c1 70 05 40 00 mov $0x400570,%rcx 
40046d: 48 c7 c7 34 05 40 00 mov $0x400534,%rdi 
400474: e8 bf ff ff ff   callq 400438 <[email protected]> 
400479: f4      hlt  
40047a: 90      nop 
40047b: 90      nop 

結束而這只是衆多例子中的一個,但你的想法。爲什麼C代碼以這種方式編譯?提前致謝。

回答

7

很多時候這些只是用來做填充,以便後續的東西再次開始在一個單詞或邊界,因爲訪問任意代碼,在字邊界上不對齊的任意代碼對於cpu來說要昂貴得多。

17

添加了nop以強制下一個函數與4字節邊界對齊。 (請注意,在最後一個nop之後的地址將爲40047c,可以被4整除)

+0

在x86_64上,我還注意到函數中間有一個4字節的nop(在「調用」之前):' 0f 1f 40 00 \t nop DWORD PTR [rax + 0x0]'任何想法什麼是好的? '-O3'處發生。 – 2013-07-09 12:37:14

+1

@Kerrek如果我記得正確,那就告訴處理器清除它的緩存並用指向地址處的數據重新加載它。在這種情況下,處理器會用'[rax]'(我認爲這是呼叫跳轉到的地址)的數據擦除緩存。這允許處理器在跳轉之前開始使用正確的數據重新加載其緩存。 – 2013-07-30 21:04:41