2016-03-02 40 views
-1

我在網上找到了一些建議。裝配中的Sqrt x86

我也有類似的問題,但沒有任何的建議,幫助(或者我沒弄明白正確如何根據我的計劃實現它們)。

代碼在C程序中插入爲asm(...)

-masm=intel,編譯後的使用:

asm ("FLD EBX \n" "FSQRT \n" "FST EBX \n"). 

我得到的編譯錯誤:

: 」 「錯誤的 'FLD' 數類型不匹配」 ......不匹配 'FST' 」。

EBX在這些命令之前保留一些整數正值。

那麼獲取ebx = sqrt(ebx)的正確方法是什麼?

+5

您不能從通用寄存器加載到FPU中。你需要經歷記憶。請參閱指令集參考。 '推ebx; fild dword [esp]; FSQRT; fistp dword [esp];流行ebx'。請注意,通常不需要組裝,並且gcc內聯彙編是一個複雜的野獸。 – Jester

+1

請製作一個[mcve]而不是一個簡單的代碼片段。 – fuz

+0

@Jester嘿我在一些網站看到這個方案,但不明白我應該插入什麼,而不是dword和esp? – user5618793

回答

4

您應該在現代代碼中使用SSE/SSE2 for sqrt,而不是x87。用一條指令可以直接將gp寄存器中的整數轉換爲xmm寄存器中的double。

cvtsi2sd xmm0, ebx 
sqrtsd xmm0, xmm0  ; sd means scalar double, as opposed to SIMD packed double 
cvttsd2si ebx, xmm0  ; convert with truncation (C-style cast) 

; cvtsd2si ecx, xmm0 ; rounded to nearest integer (or whatever the current rounding mode is) 

這適用於64位整數,太(rbx),但要注意double只能完全代表整數高達約2^53(尾數大小)。如果你想檢查一個整數是否是一個完美的正方形,你可以使用float sqrt,然後對整數結果進行試乘。 ((a*a) == b

有關指南,教程和手冊的鏈接,請參閱


需要注意的是,插入碼到C程序中的中間是完全錯誤的做法。 GNU C inline asm是實現asm最困難的方式,因爲您必須真正瞭解所有事情才能正確使用約束。讓他們錯誤可能會導致其他周圍的代碼以微妙而難以調試的方式破壞,而不僅僅是您在內聯asm錯誤時所做的事情。有關這方面的更多詳細信息,請參閱x86標記wiki。

如果你想int a = sqrt((int)b),那麼寫在你的代碼,讓編譯器爲你生成這三個指令。通過一切手段閱讀和理解編譯器的輸出,但不要盲目地在asm("")的中間插入一個序列。

例如爲:

#include <math.h> 
int isqrt(int a) { return sqrt(a); } 

​​(GCC 5.3沒有-ffast-數學):

pxor xmm0, xmm0  # D.2569 
    cvtsi2sd  xmm0, edi  # D.2569, a 
    sqrtsd xmm1, xmm0 # tmp92, D.2569 
    ucomisd xmm1, xmm1  # tmp92, tmp92 
    jp  .L7 #, 
    cvttsd2si  eax, xmm1  # D.2570, tmp92 
    ret 
.L7: 
    sub  rsp, 8 #, 
    call sqrt # 
    add  rsp, 8 #, 
    cvttsd2si  eax, xmm0  # D.2570, tmp92 
    ret 

我想sqrt()必須設置errno在某些類型的錯誤。:/

隨着-fno-math-errno

pxor xmm0, xmm0  # D.2569 
    cvtsi2sd  xmm0, edi  # D.2569, a 
    sqrtsd xmm0, xmm0 # tmp92, D.2569 
    cvttsd2si  eax, xmm0  # D.2570, tmp92 
    ret 

pxor是打破XMM0以前的內容虛假的依賴,因爲cvtsi2sd做出的奇怪的設計決定離開DEST載體的上半章修改。如果您想要將轉換結果插入現有向量中,這種方法纔有用,但已經有cvtdq2pd來執行打包轉換。 (他們可能沒有考慮64位整數,因爲當Intel發佈SSE2時,AMD64仍然在繪圖板上)。

+0

我覺得它比我更復雜一點, ve預期..謝謝! – user5618793