2017-08-15 110 views
1

假設我們有一個C(或C++)具有以下簽名功能:Win64 vs System V ABI(x86_64):Win64跳過註冊?

void foo(int64_t a, double b, int64_t c, double d); 

當在Linux,Mac,或者使用System V的ABI(x86_64的)任何OS編譯,ac獲得通過的rdirsi寄存器,bd通過xmm0xmm1。好的,這沒什麼不妥。但是,我在Windows(x86_64)中也是這樣做的,它看起來像跳過了一些寄存器。 acrcxr8獲得通過(rdx跳過),以及bd獲得通過在xmm1xmm3xmm0xmm2跳過)。爲什麼Win64會這樣做而不是「壓縮」像System V這樣的參數?對於System V,我想象能夠傳遞4個qwords和4個雙打而不需要傳遞堆棧中的任何東西,而我猜測Win64會傳遞任何東西超過堆棧中的第4個參數。

我知道在Win64與SysV中傳遞參數時寄存器順序的差異,但順序應該不相關。我只是好奇爲什麼Win64會跳過寄存器,特別是當它只有4個非棧參數傳遞。

+0

完全不同的abi,我認爲我認爲老勝abi被稱爲fastcall不知道約64位...我只知道它是不同的... –

+1

這有點難以回答,我們可以推測,但在最後只有設計師*真的*知道他們的理由 – harold

+0

請注意,Win64 ABI在寄存器中傳遞最多四個整數/指針參數,而System V ABI傳遞多達六個寄存器(請參閱https://en.wikipedia.org/維基/ X86_calling_conventions)。在Win64中用於這個目的的四個都是System V中使用的六個。我不認爲說Win64 ABI *跳過*寄存器是不合適的,但肯定指定它們中的更少用於使用。至於爲什麼它這樣做,但是,我懷疑你會在這裏得到解釋。 –

回答

2

微軟的文檔

https://docs.microsoft.com/sv-se/cpp/build/parameter-passing

指出,他們通過在寄存器中最多4個參數。如果一個參數不適合特定的寄存器,那麼該寄存器就會被跳過。 「

」浮點型和雙精度參數在XMM0 - XMM3(最多4個)中傳遞,整數槽(RCX,RDX,R8和R9)通常用於該基數槽被忽略(見例子),反之亦然。「

例3所鏈接的頁面上正好是你的榜樣,並解釋你所看到的效果:

func3(int a, double b, int c, float d);  
// a in RCX, b in XMM1, c in R8, d in XMM3 

所以他們使用最多4個寄存器參數,第一個參數在任何RCX或XMM0, RDX或XMM1中的第二個參數等。

那麼爲什麼要這樣做呢?也許將8個寄存器參數傳遞給函數的想法似乎不是一個重要的用例。

+0

我只是好奇,如果這個註冊跳過行爲對性能或什麼的影響可以忽略不計,因爲Windows肯定不是操作系統的笑話。 –

+2

這將意味着可變數量的參數主頁空間,並使可變參數函數難以實現。 –