FPU以fld存储nan

时间:2013-01-20 10:58:40

标签: assembly floating-point x86 masm fpu

我正在汇编中编写DOS程序:我正在尝试绘制Mandelbrot集。我现在正试图在汇编中翻译这段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调试器告诉我fldnan存储在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 个答案:

答案 0 :(得分:2)

我看到的一个问题是,您没有将dses设置为指向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