2016-03-31 116 views
0

正如你可能已經猜到的問題是gcc自動保存被調用保存寄存器還是應該自己做?我認爲gcc會爲我做的,但是當我gcc a.c && objdump -d a.out後寫了這個代碼確實gcc保存被調用者保存寄存器

void foo(void) { 
    __asm__ volatile ("mov $123, %rbx"); 
} 

void main(void) { 
    foo(); 
} 

我看到這個

00000000004004f6 <foo>: 
    4004f6: 55      push %rbp 
    4004f7: 48 89 e5    mov %rsp,%rbp 
    4004fa: 48 c7 c3 7b 00 00 00 mov $0x7b,%rbx 
    400501: 90      nop 
    400502: 5d      pop %rbp 
    400503: c3      retq 

0000000000400504 <main>: 
    400504: 55      push %rbp 
    400505: 48 89 e5    mov %rsp,%rbp 
    400508: e8 e9 ff ff ff   callq 4004f6 <foo> 
    40050d: 90      nop 
    40050e: 5d      pop %rbp 
    40050f: c3      retq 

據ABI x86-64的是%rbx被叫保存登記,但在這代碼gcc在修改之前未將其保存在foo中。僅僅是因爲我在調用foo()之後沒有在主要功能中使用%rbx,或者因爲gcc不提供這樣的服務,我必須在修改之前自己將其保存在foo之前?

+2

GCC不關注你的內聯asm,它只是逐字地發佈它。這取決於你做正確的事情。 –

+1

這將是非常糟糕的代碼,通過死記硬背保存和恢復每個寄存器。 –

+0

@WeatherVane所以這意味着'gcc'不會預先保存這個寄存器,我應該自己保存它們嗎? – PepeHands

回答

3

海灣合作委員會將自動保存和恢復所有被調用者保存寄存器它的知識使用。它知道它自己使用的寄存器,但只知道內聯彙編中使用的寄存器(如果你告訴它)。這就是「則會覆蓋」名單是什麼:

void foo(void) { 
    __asm__ volatile ("mov $123, %%rbx" : : : "rbx"); 
} 

現在編譯器知道你正在使用/修改RBX,因此,如果需要將其保存。

請注意,您確實想要這樣做,而不是試圖自己保存它,因爲如果gcc也想在此函數中使用寄存器,它將只會被保存一次。

+0

'asm'關鍵字優先於'__asm__',除非您'重新編寫需要工作的庫代碼,即使用戶做了類似'#define asm 1'的工作,哦,但是OP使用了'__asm__',所以你只需要遵循該代碼 –

+0

感謝您的解釋良好! – PepeHands

1

這將是相當麻煩的代碼,通過死記硬背保存和恢復每個寄存器。編譯器將寄存器保存在它編譯的C代碼中,但是你自己在這裏,gcc不知道你的意圖是什麼。

彙編程序可以讓你得到引擎蓋,但它不會替代你的火花塞。