środa, 27 maja 2009

Wywołanie funkcji pow w asemblerze (crt_pow)

Dzisiaj natknąłem się na niemały problem.. jak można potęgować dwie liczby zmiennoprzecinkowe w asemblerze. Poszukiwania zacząłem od plików nagłówkowych masma, ale niestety jedyny mój trop właściwie prowadził tylko do funkcji crt_pow. Ale niestety, biblioteki masma są wręcz beznadziejnie opisane (w przeciwieństwie do MSDN :P) więc zajęło mi trochę czasu, by cokolwiek znaleźć przez google.. ale nic nie wygooglowałem. Także trzeba było znaleźć rozwiązanie metodą prób i błędów. Rozwiązanie okazało się dosyć proste ;)

Najpierw musimy dołączyć do naszego programu nagłówek msvcrt.inc oraz bibliotekę msvcrt.lib. Następnie w odpowiednim miejscu programu wpisujemy:
LOCAL tmp:DWORD ; potrzebujemy zmiennej pomocniczej
...
finit ; inicjujemy koprocesor
mov tmp, 2 ; pobieramy liczbę 2
fild tmp ; wrzucamy ją na stosu koprocesora
mov tmp, 5 ; pobieramy liczbę 5
fild tmp ; wrzucamy ją na stos koprocesora
; teraz mamy st0 = 5, st1 = 2
sub esp, 16 ; inicjujemy 16 bajtów miejsca na stosie programu
fstp qword ptr[esp] ; pierwszą liczbą umieszczoną na stosie jest 5
fstp qword ptr[esp+8] ; drugą - 2
call crt_pow ; obliczamy 5^2
add esp, 16 ; "zdejmujemy" dwie liczby ze stosu
; z otrzymaną wartością można zrobić cokolwiek ;)


Wynik potęgowania pozostaje w st0, czyli na szczycie stosu koprocesora. Jak widać, nie jest to aż tak trudne zadanie jak się może wydawać ;) Ważne jest, by pamiętać o odpowiednich zmianach wartości wskaźnika stosu.

Mam nadzieję, że choć komuś to pomogło, w szczególności osobom, które nie mają zbyt wiele doświadczenia w asemblerze.