Saya sedang mengerjakan program yang memecahkan akar persamaan kuadrat. Saya bisa mendapatkan root pertama di subrutin root1. Namun, ketika saya mencoba mencari akar kedua di root2, bagian "/2a" dari rumus kuadrat tetap menghasilkan NaN.

Berikut kodenya:

INCLUDE Irvine32.inc    
INCLUDE macros.inc

.data                                                   
a real8 ?
b real8 ?
cc real8 ?

a2 real8 ?
b2 real8 ?
cc2 real8 ?

two real8 2.0
four real8 4.0

two2 real8 2.0
four2 real8 4.0

ten real8 1000.0
num real8 10.0


.code                                   
main PROC       
    finit 
    mWrite "Enter coefficient (a): "
    call ReadFloat
    fst a
    fstp a2

    mWrite "Enter coefficient (b): "
    call ReadFloat
    fst b
    fstp b2

    mWrite "Enter coefficient (c): "
    call ReadFloat
    fst cc
    fstp cc2
    
    mWrite "Roots: "
    call root1
    call Crlf
    call root2

    ;call showfpustack
exit
main ENDP

root1 PROC
    
    ; b^2
    fld b
    fmul b
    fchs    ; flip sign
    fst b
    
    ; 4 * a * c
    fld four
    fmul a
    fmul cc
    fchs
    fsub b 
    fsqrt
    fst four


    fld b
    fchs
    fsqrt
    

    fchs
    fadd four
    fst b

    fld two
    fmul a
    fst two


    fld b
    fdiv two

    call WriteFloat
    call showfpustack

    ret
root1 endp

root2 PROC

    fld b2
    fmul b2
    fchs
    fst b2


    fld four2
    fmul a2
    fmul cc2
    fchs
    fsub b2
    fsqrt
    fst four2


    fld b2
    fchs
    fsqrt


    fchs
    fsub four2
    fst b2

    call Crlf
    call WriteFloat

    fld two2
    fmul a2
    fst two2

    fld b2
    fdiv two2

    call showfpustack
    ret
root2 endp
end main

Saya dapat memverifikasi hasil perhitungan sebelumnya. Hanya bagian ini yang membuat saya kesulitan.

1
Nico 19 November 2020, 09:36

1 menjawab

Jawaban Terbaik

Daripada berspekulasi tentang mengapa Anda mendapatkan NAN, saya akan memandu Anda melalui kode yang perlu Anda tulis untuk menghitung akar persamaan kuadrat.
Anda melihat bahwa Anda tidak memerlukan konstanta apa pun dalam memori dan Anda juga tidak memerlukan banyak salinan input a, b, dan c.

Setel ulang lingkungan FPU

fninit

Simpan konstanta menarik yang akan kita gunakan kembali beberapa kali:

fld     a             ; (st0) a
fadd    st0           ; (st0) a + a == 2a

Menghitung D = b^2 - 4ac

fld     b             ; (st0) b                 (st1) 2a
fmul    st0           ; (st0) b * b == b^2      (st1) 2a

fld     c             ; (st0) c                 (st1) b^2  (st2) 2a
fmul    st2           ; (st0) c * 2a == 2ac     (st1) b^2  (st2) 2a
fadd    st0           ; (st0) 2ac + 2ac == 4ac  (st1) b^2  (st2) 2a

fsubp                 ; (st0) b^2 - 4ac == D    (st1) 2a

Di sini kita perlu menguji apakah D tidak negatif karena tidak ada akar untuk D<0.

ftst                  ; This compares st0 to 0.0 and sets flags C3, C2, and C0
fnstsw  ax            ; Copies those flags to AX
sahf                  ; Copies those flags to EFLAGS
jp      IsUnordered   ; This should not happen
jc      IsNegative    ; This is very possible

Kita dapat mengambil akar kuadrat hanya jika D tidak negatif.

fsqrt                 ; (st0) sqrt(D)                   (st1) 2a

Pergi untuk root pertama R1:

fld     b             ; (st0) b                         (st1) sqrt(D)  (st2) 2a
fchs                  ; (st0) -b                        (st1) sqrt(D)  (st2) 2a
fsub    st1           ; (st0) -b - sqrt(D)              (st1) sqrt(D)  (st2) 2a
fdiv    st2           ; (st0) (-b - sqrt(D)) / 2a == R1 (st1) sqrt(D)  (st2) 2a

Pergi untuk root ke-2 R2:

fld     b             ; (st0) b                         (st1) R1  (st2) sqrt(D)  (st3) 2a
fchs                  ; (st0) -b                        (st1) R1  (st2) sqrt(D)  (st3) 2a
fadd    st2           ; (st0) -b - sqrt(D)              (st1) R1  (st2) sqrt(D)  (st3) 2a
fdiv    st3           ; (st0) (-b - sqrt(D)) / 2a == R2 (st1) R1  (st2) sqrt(D)  (st3) 2a

Pada titik ini tumpukan register FPU hanya memiliki 4 entri:

st3 = 2a
st2 = sqrt(D)
st1 = R1
st0 = R2

Harap dicatat bahwa tidak ada dalam kode ini saya harus menyimpan apa pun kembali di memori. Bekerja dengan FPU adalah masalah perencanaan yang matang. Mengatur ulang ekspresi seringkali menguntungkan dan menggunakan kembali nilai yang dihitung sebelumnya selalu merupakan kemenangan.

2
Sep Roland 19 November 2020, 19:47