Search code examples
assemblymasmx86-16

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.


Solution

  • 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