2016-02-10 53 views
0

到現在爲止,我用內聯asm來破解它不是獲得良好性能的最佳選擇。我從彙編開始,但是我正在編寫我的機器(GCC),但結果代碼是在64位(Sandy Bridge & Haswell)中的其他(ICC)上運行的。在不同的編譯器中定義一個彙編函數

要調用一個沒有參數的函數,我們可以用CALL來做,但我不太明白如何用參數調用一個函數,並且因爲我試圖在所有函數中使用內聯__asm__。這是一個不錯的選擇?

我的功能:

void add_N(size_t *cnum, size_t *ap, size_t *bp, long &n, unsigned int &c){ 

    __asm__(
     //Insert my code here 
    ); 

} 

當我看到拆卸(海灣合作委員會),我有:

add_N(unsigned long*, unsigned long*, unsigned long*, long&, unsigned int&): 
0x100001ff0 <+0>: pushq %rbp 
0x100001ff1 <+1>: movq %rsp, %rbp 
0x100001ff4 <+4>: movq %rdi, -0x8(%rbp) 
0x100001ff8 <+8>: movq %rsi, -0x10(%rbp) 
0x100001ffc <+12>: movq %rdx, -0x18(%rbp) 
0x100002000 <+16>: movq %rcx, -0x20(%rbp) 
0x100002004 <+20>: movq %r8, -0x28(%rbp) 
0x100002008 <+24>: popq %rbp 
0x100002009 <+25>: retq 

我明白髮生了什麼..請問不同的編譯器/微架構總是將相同的寄存器地址關聯起來,如果函數簽名是相同的?


然後把一些代碼我的功能(不__ASM__ CODE),以及desassembly PUSH很多寄存器裏面。爲什麼發生?爲什麼我不需要推%rax%rsi(例如),並且需要推r13,r14r15? 如果我需要推r**寄存器,我可以在inline __asm__嗎?

0x100001ea0 <+0>: pushq %rbp 
0x100001ea1 <+1>: movq %rsp, %rbp 
0x100001ea4 <+4>: pushq %r15 
0x100001ea6 <+6>: pushq %r14 
0x100001ea8 <+8>: pushq %r13 
0x100001eaa <+10>: pushq %r12 
0x100001eac <+12>: pushq %rbx 
0x100001ead <+13>: movq %rdi, -0x30(%rbp) 
0x100001eb1 <+17>: movq %rsi, -0x38(%rbp) 
0x100001eb5 <+21>: movq %rdx, -0x40(%rbp) 
0x100001eb9 <+25>: movq %rcx, -0x48(%rbp) 
0x100001ebd <+29>: movq %r8, -0x50(%rbp) 
+2

'jmp'是一個無條件的*跳轉*,而不是*調用*。如果你對一個函數執行'jmp',然後使用'ret'指令返回,堆棧將不會正確設置返回,你將會有一些非常奇怪的行爲,因爲'ret'指令會跳到一些未知的位置。 –

+0

謝謝你,我說因爲我在其他地方讀過它.. –

回答

1

對於最後一個問題 - 是的,只要它們使用相同的ABI,它將使用相同的寄存器參數。 Linux x86_64 ABI在這裏定義:http://www.x86-64.org/documentation/abi.pdf並且所有編譯器必須符合它。具體來說,您對第16頁感興趣 - 參數傳遞。

我相信Windows有略微不同的ABI。所以你不能運行在Linux上編譯的程序或庫,例如在Windows上運行(但還有其他一些原因)。

有關gcc內聯彙編的詳細信息,請查看一些現有教程,因爲它是相當長的主題。這是一個好的開始:http://asm.sourceforge.net/articles/rmiyagi-inline-asm.txt

+0

謝謝你,你能看到在這段時間內出現的疑問嗎? –

+0

@HélderGonçalves:用gcc解釋內聯彙編是一件相當困難和長期的任務。最好看看這樣的一些教程:http://asm.sourceforge.net/articles/rmiyagi-inline-asm.txt –

+1

我不認爲這是相當正確的(相同的寄存器將/總是/是用於參數)。例如,如果函數被內聯,我不相信你會找到你期望的參數。另外,如果使用-fwhole-program優化,gcc可能會決定不使用這些參數(儘可能看到),並且不會通過它們。 OP建議的風險很大,我不會依賴它。創建一個'extern'asm例程並鏈接它應該得到他想要的/期望的行爲。如果您必須使用內聯彙編,請使用#ifdef來檢測各種支持的編譯器。 –