FPU хранит Nan с полями

Я пишу DOS-программу в сборке: я пытаюсь нарисовать множество Мандельброта. Я сейчас пытаюсь перевести этот кусок кода C в сборке:

double x0 = i * 3.2 / maxX - 2.1; //scaled x coordinate of pixel (-2.1, 1.1)

Я перевел это как:

finit
fld     scaleX  ;contains 3.5, declared with
fimul   xCoord  ;the i coordinate
fidiv   maxX    ;maximum width (320)
fsub    offsetX ;result is scaleX * xCoord / maxX - offsetX
fstp    x0      ;store the result in x0

К сожалению первый fld выходит из строя. Отладчик WD говорит мне, что fld магазины nan в ST(0) Регистр FPU. Зачем? Что я делаю неправильно? Вот полная программа: http://pastebin.com/KDrn5aLD

.387
assume cs:cseg, ds:dseg

uint    TYPEDEF word
integer TYPEDEF word
float   TYPEDEF real4
double  TYPEDEF real8

largh   =       320     ;larghezza dello schermo
alt     =       200     ;altezza dello schermo

dseg    SEGMENT para public 'data'
maxX    integer 0
maxY    integer 0
xCoord  integer 0
yCoord  integer 0       
x0      double  0.0     ;coordinata x del pixel riscalata a (-2.1 - 1.1)
y0      double  0.0     ;coordinata y del pixel riscalata a (-2.1 - 1.1)
scaleX  double  3.2
scaleY  double  2.0     ;scala in X ed in Y delle coordinate
offsetX double  2.1
offsetY double  1.0

x       double  0.0
y       double  0.0     ;valori della serie in un determinato punto (xo, yo)
zeroConst       double  0.0     ;costante double 0.0


dseg    ENDS
cseg    SEGMENT
START:
        mov     maxX, largh
        mov     maxY, alt

        mov     xCoord, 0
forX:   cmp     xCoord, largh
        jae     finish

        ;mov    dl,69
        ;mov    ah,2
        ;int    21h     ;test loop forX

        mov     yCoord, 0
        cmp     yCoord, alt
        jae     nextX
forY:   cmp     yCoord, alt
        jnb     nextX

        ;forY code here
        finit
        fld     scaleX  ;coordinate X
        fimul   xCoord
        fidiv   maxX
        fsub    offsetX ;calcolo scala * coordinata / coordinataMax - offset
        fstp    x0


;       fld     scaleY  ;coordinate Y
;       fimul   yCoord
;       fidiv   maxY
;       fsub    offsetY ;calcolo scala * coordinata / coordinataMax - offset
;       fstp    y0
;       
;       fld     zeroConst
;       fst     x
;       fstp    y



        inc     yCoord
        jmp     forY

nextX:  inc     xCoord
        jmp     forX

finish: mov     dl, 70
        mov     ah, 2
        int     21h

        mov     ah, 4Ch ;DOS terminate opcode
        xor     al, al
        int     21h     ;DOS call       
cseg    ENDS
END     START

1 ответ

Решение

Одна проблема, которую я вижу, это то, что вы не настраиваете ds а также es указать на dseg сегмент. Вы несете ответственность за это для программ.EXE, а не для DOS, ассемблера или компоновщика.

Измените код следующим образом:

cseg    SEGMENT
START:
        mov     ax, dseg
        mov     ds, ax
        mov     es, ax
        mov     maxX, largh
        mov     maxY, alt
        ...

Также у вас нет сегмента стека, что плохо, поскольку прерывания могут перезаписать ваш код или данные.

Добавить один:

sseg segment stack 'stack'
  dw 2048 dup (?)
sseg ends
Другие вопросы по тегам