Yes, you were right, as usual, but I think is better use cld/std before it is needed, also pushf/popf to avoid problems...
Comments in spanish, sorry.
; *************************************************************
; * Print a real number on the screen *
; * (c) Alfonso Víctor Caballero Hurtado *
; * http://www.abreojosensamblador.net/ *
; * You can use it but, credit ;), don't be a lamer *
; *************************************************************
; 1.005
; 0 01111111 00000001010001111010111b = 3F 80 A3 D7h
; 0.0005
; 0 01110100 00000110001001001101111b = 3A 03 12 6Fh
; 2^(116-127) * 1.00000110001001001101111
; 1 10000111 00110001101000000000000b = C3 98 D0 00h
; -1 * 2^(135-127) * 1.00110001101 = -100110001.101 = -305.625
cbFinChar EQU "$"
cbNFloats EQU 5
%MACRO PrintFloat 1
mov ah, 9
mov dx, %1
int 21h
%ENDMACRO
[org 100h]
[section .text]
mov ecx, cbNFloats
mov esi, vdNumero
@Bucle:
call FTOA
PrintFloat di
add esi, 4
loop @Bucle
; Salimos al DOS
ret
FTOA:
; Propósito: Convierte float number en ASCII
; Entrada : esi: número en coma flotante
; Salida : di: dirección donde empezar a imprimir
; Destruye : Ninguna
push ebx
push ecx
push edx
push esi
mov eax, [esi]
; Recogemos el signo (1 bit: extremo izquierda)
mov byte [rbSigno], 0 ; Suponemos sin signo
shl eax, 1
jnc .Sgte1
mov byte [rbSigno], 1
.Sgte1:
; Recuperamos el exponente (8 bits siguientes)
mov ebx, eax
shr ebx, 23+1
sub ebx, 127
mov word [rwExpon], bx
xor cx, cx ; Suponemos exponente positivo
or bx, bx
jns .ExpPositivo
mov cx, bx
neg cx
mov word [rwExpon], 0
.ExpPositivo:
; Recuperamos la mantisa
shl eax, 7 ; Eliminamos el exponente
or eax, 10000000000000000000000000000000b ; Ponemos el 1.
shr eax, 9 ; Lo ponemos su sitio, ya sin exponente
call CheckExpNeg
mov ecx, 0
.Sin_Exp: ; Eliminamos los ceros a la derecha
inc ecx
mov ebx, eax
shr eax, 1
jnc .Sin_Exp
mov eax, ebx
mov dword [vdLonMantisa], 23
sub dword [vdLonMantisa], ecx
; Recogemos la parte entera
mov ebx, eax ; eax ya tiene el 1. y no tiene ceros a la derecha
mov cx, word [vdLonMantisa]
sub cx, word [rwExpon]
and ecx, 0FFFFh ; Eliminamos la parte de arriba, por si acaso
mov dword [vdLonDecimal], ecx
shr ebx, cl ; Eliminamos decimales, sólo queda parte entera
mov word [rwEntera], bx ; Parte entera
; Recogemos la parte decimal
mov ebx, eax ; eax ya tiene el 1. y no tiene ceros a la derecha
mov cx, 32 ; 16
sub cx, word [vdLonDecimal]
shl ebx, cl ; Eliminamos la parte entera
shr ebx, cl ; Ponemos parte decimal contra borde derecho
; ** Aquí ya hemos desmenuzado el número real,
; ** ahora hay que convertirlo a ascii
; Parte decimal
call InitSum
mov ecx, dword [vdLonDecimal] ; Contador de posiciones
.B_Decimal:
shr ebx, 1
jnc .B_Sgte1
call Divide ; Resultado en vmBufDivision
call Suma ; Resultado en vdSumaFinal
.B_Sgte1:
dec ecx
jnz .B_Decimal
call Sum2ASCII ; Convierte la suma en ASCII
call CopiaSumaMatFinal ; Copiamos la suma en la matriz final
; Separador
mov byte [di], '.'
dec di
; Parte entera
mov ax, [rwEntera]
call Bin2ASCII
; Signo
cmp byte [rbSigno], 1
jnz .Fin
mov byte [di], '-'
.Fin:
pop esi
pop edx
pop ecx
pop ebx
ret
CheckExpNeg:
; Propósito: Chequeamos si el exponente fuera negativo para acomodar mantisa
; Entrada : eax: Número, cx: Exponente (0 si positivo, otro caso negativo)
; eax ya tiene el 1 a la izquierda y sin exponente
; Salida : eax
; Destruye : eax
or cx, cx
jz .cen_Fin
shr eax, cl
.cen_Fin:
ret
BaseDecimal:
; Propósito: devuelve la base para los decimales
; Entrada : eax
; Salida : edx: la base
; Destruye : Ninguna
push eax
push ebx
push esi
mov ebx, 10
.b_bucle:
mul ebx
dec esi
jnz .b_bucle
mov edx, eax
pop esi
pop ebx
pop eax
ret
Bin2ASCII:
; Propósito: convierte binario a ascii y lo va metiendo en di
; Entrada : eax: num a convertir, di: donde empieza a meter en el búfer
; Salida : di donde ha terminado de meter en el búfer
; Destruye : eax, edi
push ebx
push edx
mov ebx, 10
.Bucle1:
cmp eax, 0
jz .Salir
xor edx, edx
div ebx
or dl, 30h
mov [di], dl
dec di
jmp .Bucle1
.Salir:
pop edx
pop ebx
ret
Sum2ASCII:
; Propósito: Inicializa con ceros el búfer de la suma (8 bytes)
; Entrada : Ninguna
; Salida : Ninguna
; Destruye : eax
or dword [vdSumaFinal], 30303030h
or dword [vdSumaFinal+4], 30303030h
ret
CopiaSumaMatFinal:
; Propósito: Copia el búfer de la suma en rbNumASCII
; Entrada : Ninguna
; Salida : edi
; Destruye : esi, edi
pushf
mov esi, vdSumaFinal + 7
mov edi, rbNumASCII + 19
mov ecx, 7
std ; Decrementamos
rep movsb
popf
ret
InitSum:
; Propósito: Inicializa con ceros el búfer de la suma (8 bytes)
; Entrada : Ninguna
; Salida : Ninguna
; Destruye : eax
pushf
push ecx
push edi
mov eax, 0
mov ecx, 2
mov edi, vdSumaFinal
cld
rep stosd
pop edi
pop ecx
popf
ret
Suma:
; Propósito: Suma en bytes vmBufDivision con vdSumaFinal y lo deja aquí
; Entrada : Ninguna
; Salida : vdSumaFinal
; Destruye : eax
push ebx
push ecx
push edx
push esi
push edi
mov esi, vmBufDivision+7
mov edi, vdSumaFinal+7
mov ecx, 8
mov dl, 0
.Bucle:
mov al, byte [esi]
mov ah, byte [edi]
add al, ah
add al, dl
mov dl, 0
cmp al, 10
jb .Next
mov dl, 1
sub al, 10
.Next:
mov byte [edi], al
dec edi
dec esi
loop .Bucle
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
Divide:
; Propósito: Divide 10000000 por 2^cl y lo trocea en bytes
; Entrada : ecx: exponente de 2
; Salida : vmBufDivision
; Destruye : eax
pushf
push ebx
push ecx
push edx
push edi
; Limpiamos el búfer
push ecx
mov edi, vmBufDivision
mov eax, 0
mov ecx, 8/4
cld
rep stosd
pop ecx
;
mov eax, 10000000 ; Esto es lo que dividiremos
; mov ecx, 3 ; Parámetro que indicará por cuánto dividimos
shr eax, cl ; Hademos la división por 2^cl
; Ahora troceamos la división en bytes
mov edi, vmBufDivision+7 ; Dirección donde empezamos a escribir
mov ebx, 10 ; Establecemos el divisor
.Bucle:
cmp eax, 0 ; ¿Hemos terminado?
jz .Fin
xor edx, edx ; Limpiamos de nuevo la parte superior
div ebx ; Divisimos -> cociente en edx
mov byte [edi], dl ; Guardamos el byte
dec edi ; Actualizamos puntero
jmp .Bucle
.Fin:
pop edi
pop edx
pop ecx
pop ebx
popf
ret
[section .data]
; vdNumero dd 305.625
vdNumero dd 0.0005
dd 1.0015
dd 100.0275
dd 230.0175
dd -35.0178
vdAcumDec dd 0
rbNumASCII: times 20 db ' '
db 13, 10, cbFinChar
[section .bss]
vdSumaFinal resb 8
vmBufDivision resb 8
vdLonMantisa resd 1
vdLonDecimal resd 1
rwEntera resw 1
rdDecimal resw 1
rwExpon resw 1
rbSigno resb 1
; >realcn01
; .0004998
; 1.0014996
; 100.0274962
; 230.0174863
; -35.0177992