我有一個寫入64位x86程序集(gcc和GAS的AT & T語法)的函數,它執行一些SSE2操作。我通過反彙編使用gdb檢查了結果並查看了寄存器值,所以我知道它產生了正確的結果。在retq指令之後,我得到了segementation錯誤。由於我是彙編新手(並且從未接受過任何類),我猜測我沒有正確處理函數/主程序接口。該函數需要2個指針和一個int,並且需要返回一個浮點數。 這是我如何處理的投入在我的彙編函數/輸出:函數終止時的Segfault
float foo(float *x,float *y,unsigned int s)
{
__asm__ __volatile__(
"movl -0x14(%%rbp),%%ecx \n\t" //ecx = s
"movq -0x8(%%rbp),%%rax \n\t" //rax -> x
"movq -0x10(%%rbp),%%rdx \n\t" //rdx -> y
"subq $4,%%rsp \n\t" //function result
#sse2 operations that end up with the answer in xmm4...
"movss %%xmm4,(%%rsp) \n\t" //store result
"flds (%%rsp) \n\t" //load function result
"addq $4,%%rsp \n\t" //adjust stack
"ret \n\t"
:
:"g"(s)
:"%ecx","%rax","%rdx"
);
}
而這裏似乎導致段錯誤(這是指令RET之後在拆卸)行:
0x00007fffffffe0d0 in ??()
=> 0x00007fffffffe0d0: 00 00 add %al,(%rax)
我不知道爲什麼它在執行我的函數後將rax的低位值加回到rax中,但它似乎讓事情崩潰。我是否被允許在我的彙編函數中使用rax,即使它是通用目的,而且我聲明它會被破壞?
我不確定你是否需要看到這部分,但這是gcc希望如何處理該功能;我已經提供了調用我的函數線的拆卸:
#asm dealing with function inputs
callq 0x400520 <foo>
movss %xmm0,-0x48(%rbp)
mov -0x48(%rbp),%eax
mov %eax,-0x34(%rbp)
這讓我想起我的第二個問題,爲什麼它在任意的XMM0移動價值兩個地方?如果我的函數最終在xmm0中產生了結果,或者這是否意味着我應該避免使用xmm0?我很困惑,並會感謝任何幫助。在此先感謝任何花時間閱讀我的noob帖子:)
我剛打印到一個.s文件,我認爲你是對的。讓我試試你的建議,看看它是否有效! – 2013-02-24 07:34:52
那麼,到目前爲止,我已經從我的函數中省略了ret,它不再崩潰。 – 2013-02-24 07:38:48
我應該提到,我認爲你使用的是錯誤的調用約定。你從堆棧中讀取參數,而不是從寄存器中讀出。在Linux/BSD/OS X上,它們分別位於'rdi','rsi'和'rdx',Windows使用'rcx','rdx'和'r8'。 [維基百科上的x86-64調用約定](https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions) – Dougall 2013-02-24 07:42:59