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