2013-11-01 59 views
1
__declspec(naked) void printfive() { 
    int i = 5; 
    printf("%i\n", i); 
} 

由於某些原因,此代碼有效,但我不明白i存儲在哪裏?在調用函數的框架中?它變成全球變量?如果它存儲在調用者的框架中,那麼編譯器如何知道位移,因爲您可以使用具有不同幀大小和局部變量的不同函數調用printfive()。如果它是全球性的,或者像static也許,我試圖去遞歸,我可以看到變量沒有改變,它確實不是真正的本地。但很明顯,沒有入門代碼(序言)。好吧,我明白,沒有序言,沒有框架,沒有寄存器改變,但這是值,但範圍?此說明符的行爲是否在任何參考中定義?無論如何,這是C++標準的一部分嗎?如果你主要在裏面使用asm {}(或者使用asm來調用它們,並希望確保函數沒有被優化),那麼這種功能非常棒,但是你可以和C++混合使用。但這是一種令人費解的情緒。函數聲明__declspec(naked)如何存儲局部變量?

+1

你使用什麼編譯器? –

+0

「無論如何,這是C++標準的一部分嗎?」不,你究竟想要達到什麼目標?你的目標是什麼?你爲什麼希望編寫一個沒有序言/ epilog的函數? –

+0

我正在實現類似於第四種線程的代碼語言,每個原語都是彙編程序或C函數。大多數是asm,但有時C代碼更容易閱讀,裸函數並不是註冊表。 – exebook

回答

1

從gcc手冊:

使用該屬性...來表明指定的函數不需要由編譯器生成的序言/結尾序列。程序員應該提供這些序列。可以安全地包含在裸函數中的唯一語句是沒有操作數的asm語句。應避免所有其他語句,包括局部變量的聲明,if語句等等。應該使用裸函數來實現彙編函數的主體,同時允許編譯器爲彙編器構造必要的函數聲明。

它是不是標準(以及任何__declspec__attribute__

+0

所以基本上它的工作原理,但它不應該工作 – exebook

+0

是的,沒有人保證它會工作,如果你使用'壞'的東西。我相信這將取決於實際的CPU架構/ ABI。只要堅持安全。 – keltar

+1

@exebook:它正好適用於這種情況。但你有沒有檢查你的調用者的堆棧框架是否仍然完好?它的局部變量,返回地址,異常處理的東西? – MSalters

0

進入或退出一個功能時,編譯器添加代碼以幫助的流逝或參數。當一個函數被裸體聲明時,會生成非參數變量賦值代碼,如果要獲取任何參數,則需要直接訪問相關寄存器或堆棧(取決於ABI定義的調用約定)。

在你的情況下,你沒有傳遞參數給函數,因此即使函數被聲明爲裸露,你的代碼也能工作。如果你想看到不同之處,請看一下拆解程序。