很明顯,微軟一直在修補他們的x64 abi。確切地說,他們做了什麼,什麼時候什麼時候,甚至是什麼時候都很不清楚,文件是不完整的,分散的,並且過時的。我個人認爲Agner Fog所做的reverse-engineering work只是真正可靠的信息來源。但是他沒有處理託管代碼生成。
這個在4.5中被改變的說法是不合情理的。更有可能的是,RyuJIT改變了這種情況,RyuJIT是新的x64抖動,用於替換運行緩慢且無法維護的傳統x64抖動。最初在4.5.3版本的預覽版中發佈,可能是對4.5版的說明進行解釋,但是會在4.6後增加。這種改變的一個可能的靈感是.NETCore項目,Microsoft x64 abi與Unix代碼生成器(GNU和LLVM)的區別是相當痛苦的。
但與C++編譯器代碼生成器的更改(根據Agner Fog,gack在VS2015更新中修改)不同,此更改不太可能中斷。不匹配只能發生在pinvoke中,抖動從來不支持CallingConvention.ThisCall。幸運的是,您的問題很容易回答:
緩衝區的含義是什麼?
這隻對返回「聚集類型」的方法有用。換句話說,一個不再適合CPU寄存器的值。在C#中,這是一個struct
,並進一步規定它必須是非平凡的(超過2個成員或非平凡的字段類型)。
方法調用方必須爲其返回值(「緩衝區」)在其堆棧幀中分配空間並將指針傳遞到該空間。該指針作爲該方法隱藏的額外參數傳遞。傳統上第一個參數,在隱藏this
參數之前。這使this
成爲第二個參數,因此通過RDX寄存器而不是RCX寄存器。該更改反轉訂單,this
始終是第一個參數並通過RCX傳遞,返回值指針是第二個。被調用的方法在返回之前將返回值複製到該緩衝區中。
怎麼樣,如果我們使用靜態類
只有相關的靜態方法。然後沒有額外的隱藏this
參數,所以它被省略。實際上,從以前的方式來看,沒有任何變化,隱藏的返回值指針自動總是第一個參數,並因此通過RCX傳遞。
如果這對你很重要,那麼一定要利用調試器的調試> Windows>反彙編窗口。在一個小測試程序上運行它,它很容易告訴你使用哪個寄存器。
有關x64調用約定的MSDN文檔中的[返回值](https://msdn.microsoft.com/zh-cn/library/7572ztz4.aspx)中描述了返回緩衝區:*否則,調用者將採用分配內存和傳遞返回值的指針作爲第一個參數的責任。* –