home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / BCDASM.ZIP / BCDASM / SRC / BCDIMUL.ASM < prev    next >
Encoding:
Assembly Source File  |  1997-06-03  |  4.7 KB  |  203 lines

  1.     title    BCDASM -- Copyright 1997, Morten Elling
  2.     subttl    Signed multiplication of packed signed BCDs
  3.  
  4.     include model.inc
  5.     include modelt.inc
  6.     include bcd.ash
  7.  
  8. ;
  9. ; Convert packed BCD byte to binary in AL
  10. ; Changes AH
  11. ;
  12. @PackedBCDToBin MACRO reg8
  13.     ifdifi <reg8>, <al>
  14.     mov   al, reg8
  15.     endif
  16.     ifdifi <reg8>, <ah>
  17.     mov   ah, al
  18.     endif
  19.     and   al, 0fh    ;; Convert packed to unpacked BCD
  20.     @shr  ah, 4
  21.     aad        ;; Then to binary: ax = ah*10 + al
  22.         endm
  23.  
  24. ;
  25. ; Convert binary byte to packed BCD in AL
  26. ; Changes AH
  27. ;
  28. @BinToPackedBCD MACRO reg8
  29.     ifdifi <reg8>, <al>
  30.     mov   al, reg8
  31.     endif
  32.     aam        ;; ah = al DIV 10, al = al MOD 10
  33.     @shl  ah, 4     ;; Convert unpacked to packed BCD
  34.     or    al, ah
  35.     endm
  36.  
  37.  
  38.     @CODESEG
  39.  
  40. ;//////////////////////////////////////////////////////////////////////
  41. ;//    Name    bcdImul
  42. ;//    Desc    Signed multiplication of two packed signed BCDs.
  43. ;//
  44. ;//
  45. ;//    Entry    Passed args
  46. ;//    Exit    Double-size packed signed BCD product returned to
  47. ;//        destination _replacing_ the multiplicand.
  48. ;//        Acc undefined.
  49. ;//
  50. ;//    Note    Both BCD operands must be defined as double-size, e.g.
  51. ;//            mplic  dt 456512,?
  52. ;//            mplier dt 888644,?
  53. ;//        where the high-order is undefined (because the result
  54. ;//        is returned as double-precision and the multiplier
  55. ;//        provides temporary work space for this procedure).
  56. ;//
  57. ;//        Destination and source may be the same.
  58. ;//
  59. ;//    Note    This procedure was inspired by:
  60. ;//        MPMUL1.ASM by Ray Duncan * PC Magazine Vol. 8 no. 20
  61. ;//        Copyright (C) 1989 Ziff Davis Communications
  62. ;//
  63. ;//
  64. ;//    ToDo    Rewrite loop to skip non-significant zeros.
  65.  
  66. bcdImul proc
  67. arg    dstBCD    :dataptr, \    ; Addr of multiplicand
  68.     srcBCD    :dataptr, \    ; Addr of multiplier
  69.     srcsz    :@uint        ; Byte size of each BCD (double-size)
  70. @uses    ds,es,rsi,rdi,rbx,rcx,rdx,rax
  71. ;.
  72. ; ----- Copy multiplicand to hi(src)
  73.     push  rbp
  74.     @cld            ; String ops forward
  75.     mov   rbx, [srcsz]
  76.     @LDS  rsi, [dstBCD]
  77.     @LES  rdi, [srcBCD]
  78.     mov   rcx, rbx
  79.     shr   rcx, 1
  80.     add   rdi, rcx
  81.     rep   movsb
  82.  
  83. ; ----- Zero destination
  84.     @LES  rdi, [dstBCD]
  85.     mov   rcx, rbx
  86.     sub   rax, rax
  87.     rep   stosb
  88.  
  89. ; ----- Fix pointers
  90.     @LDS  rsi, [srcBCD]    ; u[0]
  91.     sub   rdi, rbx        ; w[0]
  92.     shr   rbx, 1
  93.     lea   rbp, [rsi+rbx]    ; v[0]
  94.     ; *** No stack frame ***
  95.     lea   rdx, [rbx-1]    ; Byte size, excl. sign byte
  96.  
  97. ; ----- Perform the multiplication
  98. ;
  99. ;    for (i=0; i<m; i++) {
  100. ;      k=0;
  101. ;      for (j=0; j<m; j++) {
  102. ;        t = u[j] * v[i] + w[i+j] + k;
  103. ;        w[i+j] = t % 100;
  104. ;        k = t / 100;
  105. ;      }
  106. ;      w[i+m] = k;
  107. ;    }
  108. ;
  109. ;    Usage:
  110. ;    ds:rsi = u[0]    base address of multiplier
  111. ;    ds:rbp = v[0]    base address of multiplicand
  112. ;    es:rdi = w[0]    base address of product
  113. ;    rbx    = i    index for outer loop
  114. ;    rcx    = j    index for inner loop
  115. ;    rdx    = m    operand length in bytes
  116. ;    ah/dh  = k    remainder of partial products
  117. ;
  118.     sub   rbx, rbx        ; i = 0
  119.     @alignn
  120. @@outr: sub   rcx, rcx        ; j = 0
  121.     sub   ah, ah        ; k = 0
  122. @@innr: push  rdx        ; Save m
  123.     mov   dh, ah        ; Save k
  124.     ;
  125.     ; Since we are going to multiply and divide later on,
  126.     ; we'll convert the packed BCDs to binary before doing
  127.     ; the math in binary, then convert back to BCD.
  128.     ; Note that the remainder (ah/dh register) is a binary
  129.     ; number, not a BCD.
  130.     ;
  131.     ife @isUse32
  132.     xchg  rbx, rcx
  133.     mov   al, [rsi+rbx]    ; Get u[j]
  134.     xchg  rbx, rcx
  135.     xchg  rsi, rbp
  136.     mov   dl, [rsi+rbx]    ; Get v[i]
  137.     xchg  rsi, rbp
  138.          else
  139.     mov   al, [rsi+rcx]
  140.     mov   dl, [rbx+rbp]
  141.         endif
  142.     @PackedBCDToBin al
  143.     xchg  al, dl
  144.     @PackedBCDToBin al
  145.     mov   ah, dl
  146.     push  rax
  147.     ;
  148.     add   rbx, rcx
  149.     mov   al, @ES [rdi+rbx] ; Get w[i+j]
  150.     @PackedBCDToBin al
  151.     mov   dl, al
  152.     pop   rax
  153.     mul   ah        ; t = u[j] * v[i]
  154.     add   al, dl        ;   + w[i+j]
  155.     adc   ah, 0
  156.     add   al, dh        ;   + k
  157.     adc   ah, 0
  158.     ;
  159.     mov   dl, 100d
  160.     div   dl
  161.     mov   dh, al
  162.     @BinToPackedBCD ah
  163.     mov   @ES [rdi+rbx], al ; w[i+j] = t mod 100
  164.     mov   ah, dh        ;      k = t div 100
  165.     sub   rbx, rcx        ; Restore i
  166.     ;
  167.     pop   rdx        ; Restore m
  168.     inc   rcx        ; j++
  169.     cmp   rcx, rdx        ; j == m?
  170.     jb    @@innr        ; No, repeat inner loop
  171.     ;
  172.     @BinToPackedBCD ah
  173.     add   rbx, rdx
  174.     mov   @ES [rdi+rbx], al ; w[i+m] = k
  175.     sub   rbx, rdx        ; Restore i
  176.     inc   rbx        ; i++
  177.     cmp   rbx, rdx        ; i == m?
  178.     je sh @@zr
  179.     jmp   @@outr        ; No, repeat outer loop
  180.  
  181. ; ----- Check for zero result
  182. @@zr:    pop   rbp
  183.     ; *** Stack frame restored ***
  184.     mov   rcx, rdx
  185.     add   rcx, rcx
  186.     inc   rcx
  187.     sub   rax, rax        ; Zero acc
  188.     repz  scasb
  189.     rcr   ah, 1        ; 0 if product is zero, else 80h
  190.  
  191. ; ----- Determine product's sign
  192.     add   rdi, rcx        ; Point to sign byte
  193.     add   rsi, rdx
  194.     inc   rdx
  195.     mov   al, [rsi]     ; Get sign of multiplier
  196.     add   rsi, rdx
  197.     xor   al, [rsi]     ; XOR with sign of multiplicand
  198.     and   al, ah        ; Zero if product is zero, else 80h
  199.     stosb            ; Store sign
  200.     RET
  201. bcdImul endp
  202.  
  203.     END