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.