sqrt.asm
Program napisałem w ramach przypomnienia sobie asemblera. Zbudowany przy użyciu Netwide Assembler (32bit) i "Minimalist GNU for Windows (32bit). Wylicza pierwiastek z podanej liczby metodą Newtona.
; nasm -f win32 sqrt.asm ; ld -o sqrt.exe sqrt.obj c:\windows\system32\msvcrt.dll [bits 32] extern _scanf, _printf ;----------------------------------------------------------------- section .data info: db 10, "Program oblicza pierwiastek kwadratowy", 10, 10, 0 get_p: db "Podaj wartosc pierwiastka: ", 0 frmt: db "%lf", 0 ; format dla scanf/printf ; ; wyliczanie pierwiastka kwadratowego z danej liczby p ; metoda Newtona ; ; x1 = 0,5 * ( x0 + p / x0 ) ; c: dq 0.5 ; stala 0,5 p: dq 0.0 ; wartosc z ktorej obliczamy pierwiastek x0: dq 0.0 ; pierwsza wartosc poczatkowa rowna p x1: dq 0.0 d: dq 0.001 ; dokladnosc obliczen ;----------------------------------------------------------------- section .text _WinMain@16: push info call _printf add esp, 4 ; sciagnij ze stosu push get_p call _printf add esp, 4 push p ; adres wartosci - drugi parametr dla scanf push frmt ; pierwszy parametr dla scanf call _scanf add esp, 8 finit ; inicjalizacja FPU fld qword[p] ; st0 = p fstp qword[x0] ; x0 = p i sciagamy wartosc z st0 loop: fld qword[p] fdiv qword[x0] ; = p / x0 fadd qword[x0] ; = x0 + p / xo fmul qword[c] ; = 0.5 * (x0 + p / x0) fst qword[x1] ; x1 = 0.5 * (x0 + p / x0) fsubr qword[x0] ; x0 - x1 -> st0 = x1 ; wiec odejmujemy odwrotnie fcom qword[d] ; porownaj x0 - x1 z 0.001 fstsw ax ; przenies rejestr stanu FPU do ax ; AH | AL ;15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ; C3 C2 C0 ; ; C3 C2 C0 ; If ST(0) > source 0 0 0 ; If ST(0) < source 0 0 1 ; If ST(0) = source 1 0 0 ; If ST(0) ? source 1 1 1 sahf ; prznies kody stanu z AH do rejestru flag ; 7 6 5 4 3 2 1 0 ; SF:ZF:xx:AF:xx:PF:xx:CF ; ja more ; jesli st > 0.001 ; jump if above (CF=0 and ZF=0) jbe end ; jesli st <= 0.001 ; jump if below or equal (CF=1) (ZF=1) more: ffree st0 ; zwolnij st0 fld qword[x1] ; st0 = x1 fstp qword[x0] ; x0 = x1 jmp loop end: push dword [x1 + 4] ; printf oczekuje wartosci double push dword [x1] push frmt call _printf add esp, 12 xor eax, eax ret ;