Działania na liczbach zmiennoprzecinkowych w Assembly

0

Cześć wszystkim

Ostatnio uczę się działań arytmetycznych w Assembly operując na liczbach zmiennoprzecinkowych. Dziś zacząłem tę naukę i poznałem kilka podstawowych instrukcji, które pozwalają działać na FPU. Są to instrukcje: fld, fstp, a teraz przyszedł czas dokładnie w tym zadaniu na fmul i fild. Niestety już dość długo męczę się z poprawnym napisaniem programu, który prosi użytkownika o inta i mnoży go przez float. (Program ma obliczać ile sekund żyje użytkownik przy czym użytkownik podaje liczbę lat jako float, a sekundy/rok są napisane w notacji wykładniczej) Dodam, że w internecie nie znalazłem przykładu programu mnożącego float i inta przy użyciu powyższych instrukcji, a dekompilacja programu napisanego w C wywaliła za dużo sztuczek kompilatora, które zapewne można zapisać bardziej zrozumiale.

Napisałem taki kod:

global _main
extern _printf
extern _scanf

section .text
_main:
	push message1
	call _printf
	add esp, 4
	
	push wiek
	push uint_format
	call _scanf
	add esp, 8

	jmp lata_na_sekundy

lata_na_sekundy:
	sub esp, 8
	fild dword [wiek]
	fld dword [sekundy_w_roku]
	fmul st0, st1
	fstp qword [esp]
	push float_format
	call _printf
	add esp, 16
	ret
		
section .data
	sekundy_w_roku dd 3.15e7
	wiek times 4 db 0
	message1 db "Podaj swoj wiek: ", 0
	uint_format db "%u", 0
	float_format db "%f", 0

Coś w tym kodzie działa nie tak jak powinno, a ja nie wiem co. Działanie instrukcji FPU rozumiem tak:
fild dword [wiek] -> przenosi inta do rejestru FPU w tym przypadku do st0
fld dword [sekundy_w_roku] -> przenosi floata do rejestru FPU w tym przypadku do st1
fmul st0, st1 -> mnoży inta w st0 z floatem w st1 i wynik działania zachowuje w st0
fstp qword [esp] -> przenosi 8 bajtów (a nie 4 bajty, ponieważ printf wymaga podania liczby zmiennoprzecinkowej jako double i wykonuje działania na double'u dopiero potem konwertuje go do floata) wyniku z st0 do wierzchołka stosu GPU, a tak właściwie do głównej pamięci

Czy coś źle rozumiem? Będę wdzięczny za naprowadzenie mnie na rozwiązanie.

0

Problem został rozwiązany toteż dam znać jeśli ktoś miałby kiedyś podobny błąd w assembly do mojego.

Otóż tak jak przypuszczałem, program wywalał się, ponieważ błędnie "czyściłem stos", a konkretniej błędnie wracałem do instrukcji powrotu. Sprawa wygląda tak:

fstp qword [esp]    ; wrzuca na wierzchołek stosu 8 bajtów
push float_format   ; ta instrukcja powoduje wrzucenie na stos standardowo 4 bajtów

Więc na stosie mamy oczywiście 12 bajtów toteż:

add esp, 12

Rozwiązuje powyższy problem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1