2015-11-15 35 views
2

我需要從C(使用extern'C'double(double num1,double num2))發送兩個實數到程序集程序,返回這些數字的加法。我不知道該怎麼做。如何在裝配中使用浮點數進行操作?

我試過這個,但沒有奏效。

.data 

res dq 0 

.code 

     procSuma proc num1,num2 

      fld num1 ; load num1 and push it onto the fpu stack 
      fld num2 ; load num2 and push it onto the fpu stack 
      faddp  ; pop two numbers, add them, push sum on the stack 
      fstp res ; pop sum from the stack and store it in res 

     procSuma endp 
end 
+2

「沒有工作」是指什麼?沒有編譯,沒有產生正確的結果,還有別的? –

+0

它沒有產生正確的結果。 –

+0

請清楚說明您的問題實際得到的預期輸出和輸出 – LBes

回答

2

你在哪裏錯的是你複製粘貼在原來未包含在功能到一個函數,我相信你從這裏得到的代碼。 Adding floating point/double numbers in assembly

由於彙編代碼現在包含在proc中,所以不再需要變量來存儲結果,因爲結果存儲在地址st(0)的堆棧中,這將是您的返回值。當調用fstp時,它會彈出堆棧(提示:最後的p),以便存儲在st(0)處的返回值不再有效。刪除fstp指令會給你預期的結果。

一步一步這是代碼正在做的事情。

procSuma proc num1,num2 

     fld num1 ; This pushes num1 onto the stack at the address of st(0) 
     fld num2 ; This pushes num2 onto the stack at the address of st(1) 
     faddp  ; This multiplies st(1) and st(0), stores the result at st(0), and then pops the variable stored at st(1) off the stack 
     fstp res ; !REMOVE THIS. This is why you aren't getting the expected result.It pops the variable in st(0) off the stack, which is your return value. 

procSuma endp 
+1

歡迎來到SO。如果你解釋了爲什麼*結果需要在st(0)中,而不是他編制的一些隨機命名的全局變量,這將是一個更好的答案。 (即由於Windows x86 32位ABI)。另外,建議在存儲後用'fld'重新加載只是令人困惑。 –

+0

謝謝@PeterCordes。這是一個「只是得到它的工作答案」水庫的重新裝載將是多餘的和貨物的文化。 –

+0

邁克爾佩奇的回答在評論中比這個答案好得多,因爲它解釋了他們的理由。這個答案沒有做很多工作來幫助迷茫的新手明白是怎麼回事,所以也不是很長期給其他人,其谷歌搜索變成了這個Q&A有用。 –

2

我假設這是一項家庭作業,需要您使用x87 FPU指令。或者,您可以使用SSE/SSE2 SIMD指令來執行添加。在Win32

Ç調用(cdecl)公約要求單精度和雙精度浮在ST(0)要返回(在FPU堆棧頂部寄存器)。由於faddp增加了兩個數字並將結果放在ST(0)表示我們不需要任何臨時變量來存儲結果。然後,這些線可以刪除

.data 
res dq 0 

fstp res ; pop sum from the stack and store it in res 

當創建您應該指定的參數的大小的程序被通過,使MASM確切地知道操作數是什麼規模進行操作。爲確保您使用雙精度值,請將參數double標記爲REAL8(8字節REALS)。您還應該將PROC標記爲使用C調用約定與PROC C,以便正確設置和解決堆棧和參數。過程聲明應該是這樣的:

procSuma proc C num1:REAL8,num2:REAL8 

生成的代碼可能看起來像:

.model flat, c 
.code 

     procSuma proc C num1:REAL8,num2:REAL8 

      fld num1 ; load num1 and push it onto the fpu stack 
      fld num2 ; load num2 and push it onto the fpu stack 
      faddp  ; pop two numbers, add them, push sum on the stack. 
         ; result in st(0) (top of FPU stack) 
         ; We return double values in st(0) so nothing to do 
         ; since faddp put our result in st(0) 
      ret 

     procSuma endp 
end 

您可以通過使用FADD而不是FADDP降低除了一對夫婦的說明:

 fld num1 ; load num1 and push it onto the fpu stack 
     fadd num2 ; Add ST(0)(num1) to num2 and store result in ST(0). 
        ; We return double values in st(0) so nothing to do 
        ; since fadd put our result in st(0)