![](/img/trans.png)
[英]How to specify clobbered bottom of the x87 FPU stack with extended gcc assembly?
[英]Why am I getting nonsensical numbers when performing operations with the FPU x87 instruction set in MASM Assembly?
我最近開始學習匯編,現在正在學習FPU x86體系結構和FPU堆棧。 我有兩個簡單的函數,可在攝氏溫度和華氏溫度之間轉換,反之亦然。
我研究了各種不同的指令,嘗試了FPU指令的各種變體,包括自動執行POP
操作的指令,並嘗試通過調試器了解我所看到的內容。 迄今無濟於事。
.386
.model flat, c
.const
r8_ftoc real8 0.5555555556 ;5/9
r8_ctof real8 1.8 ;9/5
i4_32 dword 32
.code
fahrentocel PROC
push ebp
mov ebp, esp
fld[r8_ftoc]
fld real8 ptr [ebp+8] ; load f
fild[i4_32] ; load 32
fsubp
fmulp
pop ebp
ret
fahrentocel ENDP
celtofahren PROC
push ebp
mov ebp, esp
fild real8 ptr [ebp+8] ; load c
fmul[r8_ctof]
fiadd[i4_32]
pop ebp
ret
celtofahren endp
END
C代碼:
extern "C" double fahrentocel(double temp);
extern "C" double celtofahren(double temp);
int main()
{
double celsius = 30.0;
double fahrenheit = 212.0;
double output = fahrentocel(fahrenheit);
printf("%lf", output);
}
我對華氏溫度到攝氏溫度的輸入是212.0,因此攝氏溫度輸出是100,而我從攝氏溫度到華氏溫度的轉換是30.0,所以華氏溫度的結果應該是86。
但是,相反,對於這兩個函數,我分別得到562950和858993459。 我沒有收到任何錯誤代碼,因此該函數似乎毫無例外地執行,這表明我編寫代碼的方式可能是邏輯錯誤。
這里有兩個問題。 根據使用它們的C代碼中的函數聲明,即:
extern "C" double fahrentocel(double temp);
extern "C" double celtofahren(double temp);
這兩個函數都使用double
參數,並返回double
結果。 關於接口,這很好,但是您對celtofahren
的實現則celtofahren
:
fild real8 ptr [ebp+8] ; load c
在這里,即使您自己已指示C編譯器該函數采用double值,也可以將函數的參數作為整數加載到FPU堆棧上。 因此,C編譯器發出的代碼會將double
入常規堆棧,但是由於fild
指令,您的程序集將其讀取為常規整數。 請注意, fahrentocel
正確加載了該參數。
其次,您將錯誤的格式參數傳遞給printf
,對於double
值應為f
- d
用於整數。 從而,
printf("%d", output);
應該成為
printf("%f", output);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.