J Xkcd
J Xkcd

Reputation: 423

How do I output floating point starting with zero after division?

Currently the way I do it is as follows

mov bx,divisor
div bx
mov quotient,ax
mov ax,dx
mul hundred ;--r * 100 to show 2 floating point, r * 1000 to show 3...
div bx
mov float,ax
mov floatr,dx

And then afterwards I might increment float depending on the value of floatr. Then, I will output quotient, '.', float. This works for most numbers or rather numbers with floats that start with non-zero numbers. For example, 1/100 = 0.01, however , my program will output 0.1, it doesn't output the extra zero.

Upvotes: 1

Views: 234

Answers (2)

Peter Cordes
Peter Cordes

Reputation: 364832

Write your integer output function to produce a fixed number of output digits, not stopping when repeated division by 10 produces zero.

This will give you the leading zeros you need to use this integer as the fractional part of a decimal fraction.

BTW, this is fixed-point not float-point. You're scaling to be able to handle a fixed number of places after the decimal. A floating-point representation would involve storing an exponent and significand/mantissa, not separate integer and fractional parts.

Upvotes: 0

rkhb
rkhb

Reputation: 14409

The principle is the same as in my answer here. And here is my implementation for 16-bit MASM:

.MODEL small, C
.386

.STACK 100h

.CODE

main PROC
    mov ax, 1                   ; Dividend
    mov bx, 100                 ; Divisor
    xor dx, dx                  ; Clear high 16 bit of dividend
    div bx                      ; Result: AX, remainder in DX

    call WriteDec

    mov al, '.'                 ; Decimal point
    call WriteChar

    mov cx, 10                  ; Maximal 10 digits
    L1:
    imul ax, dx, 10             ; AX = DX * 10 i.e. New dividend = Old remainder * 10
    xor dx, dx                  ; Clear the high part of dividend
    div bx                      ; AX rem. DX = DX:AX / BX
    call WriteDec
    dec cx
    jz SHORT E
    test dx, dx                 ; Is there a remainder?
    jnz L1                      ; Yes - once more

    E:
    mov ax, 4C00h
    int 21h
main ENDP

WriteDec PROC USES AX BX CX DX DI DS
    LOCAL decimal[6]:byte

    mov dx, ss
    mov ds, dx
    lea di, decimal             ; LOCAL target string decimal

    mov bx, 10                  ; divisor
    xor cx, cx                  ; CX=0 (number of digits)

    First_Loop:
        xor dx, dx              ; Attention: DIV applies also DX!
        div bx                  ; DX:AX / BX = AX remainder: DX
        push dx                 ; LIFO
        inc cl                  ; increment number of digits
        test  ax, ax            ; AX = 0?
        jnz First_Loop          ; no: once more

    Second_Loop:
        pop ax                  ; get back pushed digit
        or al, 00110000b        ; AL to ASCII
        mov byte ptr [di], al   ; save AL
        inc di                  ; DI points to next character in string DECIMAL
        loop Second_Loop        ; until there are no digits left

        mov byte ptr [di], '$'  ; End-of-string delimiter for INT 21 / FN 09h

    lea dx, decimal
    mov ah, 09h
    int 21h

    ret
WriteDec ENDP

WriteChar PROC USES AX DX
    mov dl, al
    mov ah, 02h
    int 21h
    ret
WriteChar ENDP

END main

BTW: Happy New Year

Upvotes: 2

Related Questions