clear     MACRO  Field, size
          xor    cx,cx
          mov    cl,size
          mov    al,20h
          lea    di,Field
          rep    stosb
          ENDM

Extrn     divFloat:Far
Public    Len1,Num1,Len2,Num2,Bin1,Bin2,AnsMsg,Dividend,Divisor
Public    Sign,Quotient,Remainder

          TITLE  prog04a: links with Extrn divFloat                  
          .MODEL  SMALL
          .STACK  100h

          .DATA
PgmMsg    db  0dh,0ah,0dh,0ah
          db  "This Program simulates Floating-point Division.", "$"

EnterMsg1 db  0dh,0ah,0dh,0ah
          db  "Enter Dividend in the range of -255 thru 255, now!",0dh,0ah
          db  "To Exit, press  key only.", 0dh,0ah, "$"
EnterMsg2 db  0dh,0ah,0dh,0ah
          db  "Enter Divisor in the range of 1 thru 255, now!",0dh,0ah
          db  "To Exit, press  key only.", 0dh,0ah, "$"

InBuff1   db  05
Len1      db  00
Num1      db  20h,20h,20h,20h,0dh

InBuff2   db  04
Len2      db  00
Num2      db  20h,20h,20h,0dh

InvalMsg1      db  0dh,0ah 
          db  "An Invalid Number was entered for Dividend!", 0dh,0ah, "$"
          db  "Enter a Number in the range of -255 thru 255.", 0dh,0ah,"$"
InvalMsg2      db  0dh,0ah 
          db  "An Invalid Number was entered for Divisor!", 0dh,0ah, "$"
          db  "Enter a Number in the range of 1 thru 255.", 0dh,0ah,"$"

ZeroMsg        db  0dh,0ah
          db  "The Zero was entered for Divisor!", 0dh,0ah, "$"
          db  "Enter a Nonzero number in 1 thru 255.", 0dh,0ah, "$"

Factor    db  1,1,10,100

Bin1      dw  0000
Bin2      dw  0000

AnsMsg    db  0dh,0ah,0dh,0ah, "When the Dividend is "
Dividend  db  20h,20h,20h,20h, " and the Divisor is "
Divisor   db  20h,20h,20h
          db  0dh,0ah, "the Result is "
Sign      db  20h
Quotient  db  20h,20h,20h,2eh
Remainder db  20h,20h,0dh,0ah,"$"

ByeMsg    db  0dh,0ah, "Bye for Now!", 0dh,0ah, "$"
       .CODE
MAIN           PROC
               mov   ax,@data ; get @ of data segment
               mov   ds,ax    ; set ds and es to data segment
               mov   es,ax

               lea   dx,PgmMsg  ; point to first message $ delimits message
               mov   ah,09h     ; indicate output
               int   21h        ; print message

Start:         call  ClrStorage ; clear work area
               call  GetDividnd ; get input from user
               call  ChkDividnd ; check and adjust input to binary
               call  GetDivisor ; get input from user
               call  ChkDivisor ; check and adjust input to binary
               call  divFloat   ; perform math
               jmp   Start      ; do again
MAIN           ENDP


ClrStorage     PROC
               clear Dividend,04         ; Clear Dividend field
               clear Divisor,03          ; Clear Divisor field
               clear Sign,04             ; Clear Sign & Quotient fields 
               clear Remainder,02        ; Clear Remainder field 
               ret
ClrStorage     ENDP


GetDividnd     PROC
               lea   dx,EnterMsg1 ; get @ of message to prompt user
               mov   ah,09h       
               int   21h          ; print message

               lea   dx,InBuff1   ; point dx to @ of input buffer
                                  ; byte 0 of buffer is max allowable input
                                  ; byte 1 will be count of data input
                                  ; byte 2 is start of data

               mov   ah,0ah       ; indicate that input will occur
               int   21h          ; perform input

               xor   ch,ch        ; clear high byte of cx
               mov   cl,Len1      ; get count of data read in

               cmp   cl,00        ; if no data input
               je    Exit1        ; then terminate program
               ret
        
Exit1:         lea   dx,ByeMsg    ; point to exit message
               mov   ah,09h       ; output function
               int   21h          ; perform output

               mov   ah,4ch       ; terminate function
               int   21h          ; terminate
GetDividnd     ENDP


ChkDividnd     PROC
Again1:        lea   di,Factor    ; destination index to a list of factors

               xor   dx,dx        ; zero out dx, ax, and ch
               xor   ax,ax        ; dx and ax used for math
               xor   ch,ch
               mov   cl,Len1      ; initialize cx to length of input data

               lea   si,Num1      ; point si to input data
               mov   al,[si]      ; fetch digit to al register
               cmp   al,'-'       ; if character is -
               je    LessZero     ; then handle - value

Rest1:         cmp   al,30h       ; check that the value is between 
               jl    Inval1       ; 30h and 39h - ascii 0-9
               cmp   al,39h 
               ja    Inval1

               and   al,0Fh       ; cheater's convert - throw out the 3
               push  di           ; preserve the beginning @ of factor list
               add   di,cx        ; increment into factor list by # of      
                                  ; digits in input number
               mov   bl,[di]      ; move factor to low byte of bx
               mul   bl           ; ax = al * bx
               add   dx,ax        ; add ax to dx (our accumulated value)
  
               inc   si           ; point to the next input digit
               pop   di           ; restore di to beginning of factor list
               mov   al,[si]      ; get next digit of input
               loop  Rest1        ; do again until cx = 0
        
               mov   Bin1,dx      ; store our final binary value in Bin1
               ret                ; return to call

LessZero:      mov   ah,'-'       ; put - in Sign variable - 8086 can not
               mov   Sign,ah      ; write a literal directly to memory
               dec   cx           ; move past the sign bit
               inc   si
               mov   al,[si]      ; get the next digit in the input buffer
               jmp   Rest1        ; and process normally
        
Inval1:        lea   dx,InvalMsg1 ; point to invalid message
               mov   ah,09h       ; indicate output
               int   21h          ; output message

               call  GetDividnd   ; ask the user again for a number
               jmp   Again1       ; and recheck input
ChkDividnd     ENDP


GetDivisor     PROC
               lea   dx,EnterMsg2    ; print input message 
               mov   ah,09h
               int   21h

               lea   dx,InBuff2   ; get input
               mov   ah,0ah
               int   21h

               xor   ch,ch        ; get count of digits
               mov   cl,Len2

               cmp   cl,00        ; if no input then exit
               je    Exit2
               ret
        
Exit2:         lea   dx,ByeMsg
               mov   ah,09h
               int   21h

               mov   ah,4ch
               int   21h
GetDivisor     ENDP

    
               ; Note - divisor only allows + values, final sign
               ; will be set based on sign flag set by ChkDividend
ChkDivisor     PROC
Again2:        lea   di,Factor

               xor   dx,dx
               xor   ax,ax

               xor   ch,ch
               mov   cl,Len2

               lea   si,Num2
Rest2:         mov   al,[si]
               cmp   al,30h
               jl    Inval2
               cmp   al,39h
               ja    Inval2

               and   al,0Fh
               push  di
               add   di,cx
               mov   bl,[di]
               mul   bl
               add   dx,ax
  
               inc   si
               pop   di
               loop  Rest2

               cmp   dx,0
               je    ZeroErr
      
               mov   Bin2,dx
               ret

Inval2:        lea   dx,InvalMsg2
               mov   ah,09h
               int   21h

               call  GetDivisor
               jmp   Again2

ZeroErr:       lea   dx,ZeroMsg
               mov   ah,09h
               int   21h

               call  GetDivisor
               jmp   Again2
ChkDivisor     ENDP
               END   Main