2011-08-25 17 views
5

Zostałem poproszony o napisanie prostej aplikacji w mieszanym C/ASM, który musi używać koprocesora matematycznego.x87 Instrukcje FPOP i FCOM - jak to działa?

Jest cylinder funkcyjny (float x, float y, float z), który zwraca 1, jeśli dany punkt znajduje się w cylindrze (cylinder ma podstawę przy x = 0, y = 0, promień = 5 i wysokość = 10) i 0, jeśli nie jest.

Wygląda to prosto. Sprawdź, czy z jest w zakresie < 0,10>, a następnie sprawdź, czy x^2 + y^2 < 25.

Ale moja wiedza na temat x87 jest zerowa.

Jest wszystko, co napisałem.

_cylinder PROC 

push ebp 
mov ebp, esp 
sub esp,8 ; I can't use .data in the application, so I reserve some space on the stack for numbers 10 and 25 
mov [esp],10 
mov [esp+4],25 

finit 
fldz 
fld [ebp+8] 

    ;here i get stuck 

add esp, 8 
pop ebp 
_cylinder ENDP 

Więc utknąłem. Tak więc, staram się znaleźć instrukcje, których mogę użyć w aplikacji. I tam utknąłem, ponieważ każda tutorial/lista instrukcji, którą znajduję w sieci, jest tak źle napisana, że ​​ledwo mogę zrozumieć cokolwiek.

Pytanie brzmi, co się stanie, gdy coś wyskoczę z koprocesora matematycznego? Gdzie mogę znaleźć wyskrobaną wartość? Jak przekształca się z wartości 80-bitowej na 32-bitową (oczywiście jeśli tak)? Kolejne pytanie brzmi: w jaki sposób działa FCOM (FCOMP dla wersji pop)? Porównuje co do czego (st0 do st1 lub st1 do st0?) I gdzie mogę sprawdzić, czy wartość jest mniejsza/równa/większa?

Dzięki za pomoc!

+5

Zanim pojawi się zbyt głęboko, należy rozważyć użycie SSE2 matematyki zamiast x87. Jest o wiele łatwiej pracować (możesz używać rejestrów zamiast stosu), ma więcej dostępnych funkcji i generalnie jest szybszy. – duskwuff

+0

Co powiedziałem o zmierzchu. 'x87' jest w rzeczywistości przestarzałe i nie ma powodu, by kierować go na nowe oprogramowanie. –

+0

@Stephen - "przestarzałe" dla niektórych systemów operacyjnych, nie dla procesorów, dostawców (ale nawet tam, nadal obsługiwane). Powody użycia: 80-bitowa rozszerzona precyzja i transcendentalne funkcje matematyczne. – PhiS

Odpowiedz

5

Porównywarki zmiennoprzecinkowe to rodzaj bólu. Możesz dokonać porównania na FPU, ale zanim będziesz mógł coś na tej podstawie zrobić, musisz przesłać słowo statusu zmiennoprzecinkowe do CPU, przetestować flagi, na których Ci zależy, a następnie na nie zareagować.

Wystarczy na przykład, że początkowy porównanie z> = 0,0 będzie wyglądać mniej więcej tak:

fldz 
fcomp z 
fnstsw ax 
test ah, 041h; I *think* I've got the right flags there... 
jp good 
+4

Hmm, czy nie powinno to być "test ah, ..."? [Odnośnik] (http://webster.cs.ucr.edu/AoA/Windows/HTML/RealArithmetic.html#1000117). Osobiście uważam, że używanie ['FCOMI'] (http://stackoverflow.com/questions/7057501/x86-assembler-floating-point-compare/7057771#7057771) jest łatwiejsze niż mylenie się z maskami bitowymi dla słowa statusu, jest ono dostępne tylko na P6 +. – user786653

+3

@ user786653: oops - tak, powinno być ah, nie ax. Przepraszam.Tak, FCOMI jest fajne, ale zanim nadszedł P6, nie pisałem prawie tyle kodu montażowego. Gdybym pisał dla nowszych procesorów, prawdopodobnie użyłbym SSE. –

+2

Zgadzam się, jeślibym * miał * napisać to w asemblerze x86. Wygląda na to, że OP jest ustawiony na użycie x87, więc pomyślałem, że przejdę przez to. Wydaje mi się też, że w mgnieniu oka przypomina mi się 'sahf' + unsigned tests (jak w' fcomi'). – user786653