DDP, спасибо за совет. Вот сырой вариант результата:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data
upr dw ?
flag db 0
p1 dd 0
ten dq 10.0 ; десятка для преобразования к целому
P dq ?
fig dq -100.02313e20
del dq 0 ; текущий делитель для выделения цифры
dig dd ? ; очередная цифра
string db ' .0000000000000000D-000', 0
pattern db ' .0000000000000000D-000', 0
.code
; возведение в степень x^y
pow proc x: DWORD, y: DWORD
mov eax, y
fld qword ptr [eax]
mov eax, x
fld qword ptr [eax]
ftst
fstsw ax
sahf
jnc m1 ; переход, если x >= 0
inc flag ; взведём флаг, если x < 0
fabs ;xm1: fxch
fyl2x
fst st(1)
fabs ;z; сравнимzс единицей
fld1
fcom
fstsw ax
sahf
jp exit ; операнды не сравнимы
jnc m2 ; еслиz< 1, то переход на m2
jz m3 ; еслиz= 1, то переход на m3
; еслиz> 1, то приводим к формуле z = z1+z2, где z1 - целое, z2 - дробное, и z2 < 1
xor ecx, ecx ; счётчик вычитаний
m12: inc cx
fsub st(1), st(0)
fcom
fstsw ax
sahf
jp exit ; операнды не сравнимы
jz m12
jnc m2 ; еслиz< 1, то переход на m2
jmp m12 ; еслиz> 1, то переход на m12
m3: mov p1, 1
jmp $+7
m2: mov p1, ecx
fxch
f2xm1
fadd ; компенсируем 1
fild p1 ; показатель степени для fscale
fld1
fscale
fxch
ffree st(0)
fincstp
fmul
; проверка на отрицательную степень
cmp flag, 1
jnz exit
fld1
fxch
fdiv
exit:
ret
pow endp
double2str proc fg: DWORD, buf: LPBYTE
;---------- Загрузить шаблон числа
invoke lstrcpy, buf, addr pattern
;---------- Определить и сохранить знак числа
mov edx, fg
mov eax, fg
mov eax, [eax]
and eax, 80000000h
jz positive
mov ecx, buf
mov byte ptr [ecx], '-'
;---------- Сделать из числа положительное
fld qword ptr [edx]
fabs
fstp qword ptr [edx]
positive:
;---------- Определить порядок числа
fld1
fld qword ptr [edx]
fyl2x
fldl2t
fdiv st(1), st(0)
ffree st(0)
fincstp
fstcw upr
and upr, 1111001111111111b
fldcw upr
frndint
fstp P ; порядок числа
;---------- Сформировать первый делитель
push offset ten
push offset P
call pow
fld P
fistp P
;---------- Определить и сохранить знак порядка
lea eax, P
mov eax, [eax]
cmp eax, 0
jl negative
mov ecx, buf
add ecx, 19
mov byte ptr [ecx], '+'
;---------- Сохранить сам порядок
negative:
lea eax, P
mov eax, [eax]
mov bl, 10
div bl
add ah, 30h
mov ecx, buf
add ecx, 20
mov byte ptr [ecx+2], ah
xor ah, ah
div bl
add ah, 30h
mov byte ptr [ecx+1], ah
add al, 30h
mov byte ptr [ecx], al
;---------- Вытащить и сохранить цифры
mov ecx, buf
add ecx, 2
nextDig:
fld qword ptr [edx]
fdiv st(0), st(1)
fstcw upr
or upr, 0000110000000000b
fldcw upr
frndint
fist dig
fmul st(0), st(1)
fld qword ptr [edx]
fxch st(1)
fsubp st(1), st(0)
fstp qword ptr [edx]
fld ten
fdivp st(1), st(0)
mov eax, dig
add eax, 30h
mov [ecx], al
inc ecx
cmp byte ptr [ecx], 'D'
jne nextDig
ret
double2str endp
start:
finit
push offset string
push offset fig
call double2str
invoke ExitProcess, 0
end start
(c) Vedrus
---
Возможно, через некоторое время оптимизированный вариант выложу. Если кто, что ещё посоветует по-поводу буду рад.
|