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

  1.     title    BCDASM -- Copyright 1997, Morten Elling
  2.     subttl    Addition and subtraction of packed signed BCDs
  3.  
  4.     include model.inc
  5.     include modelt.inc
  6.     include bcd.ash
  7.  
  8.     ; Note:
  9.     ; To avoid complaints from the assembler, two full-blown
  10.     ; PROC headers are used even though the two procedures here
  11.     ; use identical ARG and USES statements. Keep them in sync.
  12.  
  13. if 0
  14.     Addition        Case
  15.     x + y        = x + y    (a)    @@addn
  16.     x + (-y)    = x - y    (b)    @@srcgt, x >= y
  17.     -x + y        = y - x    (c)    @@dstgt, x < y
  18.     -x + (-y)   = -(x + y)    -(a)    @@addn
  19.  
  20.     Subtraction
  21.     x - y        = x - y    (b)
  22.     x - (-y)    = x + y    (a)
  23.     -x - y        = -(x + y)    -(a)
  24.     -x - (-y)   = y - x    (c)
  25. endif
  26.  
  27.     @CODESEG
  28.  
  29. ;//////////////////////////////////////////////////////////////////////
  30. ;//    Name    bcdAdd
  31. ;//    Desc    Add two packed signed BCD numbers (dest += src).
  32. ;//
  33. ;//
  34. ;//    Entry    Passed args
  35. ;//    Exit    Packed signed BCD sum returned to destination.
  36. ;//        Accumulator (and sf,zf,cf flags) determined:
  37. ;//        Acc = 0: No carry
  38. ;//        Acc = 1: Carry (overflow)
  39. ;//
  40. ;//    Note    Destination and source may be the same.
  41.  
  42. bcdAdd    proc
  43. arg    dstBCD    :dataptr, \    ; Addr of 1st addend (=result)
  44.     srcBCD    :dataptr, \    ; Addr of 2nd addend
  45.     BCDsz    :@uint        ; Byte size of each BCD
  46. @uses    ds,es,rsi,rdi,rbx,rcx
  47. ;.
  48.     mov   ah, 00h        ; Set up to keep sign bit
  49. join_:    @cld            ; Auto-increment index reg.s
  50.     @LDS  rsi, [srcBCD]    ; Load
  51.     @LES  rdi, [dstBCD]    ;   pointers
  52.         mov   rbx, [BCDsz]      ; Get byte size of BCD
  53.     dec   rbx        ; Handy constant
  54.     mov   rcx, rbx        ; Loop count (# digits DIV 2)
  55.  
  56. ; ----- Get number signs
  57.     mov   al, [rsi+rbx]    ; Get top byte of src
  58.     xor   al, ah        ; Keep or flip sign bit
  59.     mov   ah, al        ; Use ah to hold src's sign
  60.     mov   al, @ES [rdi+rbx] ; Get top byte of dst
  61.     and   rax, 8080h     ; Isolate sign bits
  62.     ; ah bit 7 = sign of src
  63.     ; al bit 7 = sign of dst
  64.     cmp   al, ah        ; If same sign,
  65.     jz sh @@addn        ;   add numbers
  66.  
  67. ; ----- Numbers have different signs. Find the numerically 
  68. ;    larger BCD, subtract the other from it, and use its
  69. ;    sign for the result.
  70.  
  71.     lea   rsi, [rsi+rbx-1]    ; Point to byte before sign byte
  72.     lea   rdi, [rdi+rbx-1]    ; In destination as well
  73.     std            ; Auto-decrement index reg.s
  74.     repe  cmpsb        ; Compare numbers high-to-low
  75.  
  76.     ; cmpsb flags    meaning
  77.     ; cf=1 (jc)    src < dst, use sign in al
  78.     ; cf=0 (jnc)    src >= dst, use sign in ah
  79.     ; zf=1 (je)    Treated as cf=0. Add code to handle this
  80.     ;        separately if zero results are frequent.
  81.  
  82.     jnc sh @@ahs        ; Jump if src is larger (al <> ah)
  83.     mov   ah, al        ; Set ah = sign of dst (al = ah)
  84. @@ahs:    cld            ; df = 0, ah = sign of larger number
  85.     dec   rcx        ; Adjust for mismatch by cmpsb
  86.     sub   rsi, rcx        ; Point back to LSB
  87.     sub   rdi, rcx        ;   in destination, too
  88.     mov   rcx, rbx        ; Loop count
  89.     xor   al, ah        ; If al = ah (xor clears carry)
  90.     jz sh @@dstgt        ;   then subtract src from dst
  91.  
  92. ; -----    Compute src - dst
  93.     @alignn
  94. @@srcgt:mov   al, [rsi]     ; Get two digits from src
  95.     inc   rsi        ; Step src pointer
  96.     sbb   al, @ES [rdi]    ; Subtract carry & dst digits
  97.     das            ; Decimal adjust after subtraction
  98.     stosb            ; Store al to destination
  99.     dec   rcx        ; Loop
  100.     jnz   @@srcgt        ;   until done
  101.     jmp sh @@sign        ; cf = 0
  102.  
  103. ; -----    Compute dst - src
  104.     @alignn
  105. @@dstgt:mov   al, @ES [rdi]    ; Get two digits from dst
  106.     sbb   al, [rsi]     ; Subtract carry and src digits
  107.     das            ; Decimal adjust after subtraction
  108.     stosb            ; Store al to destination
  109.     inc   rsi        ; Step src pointer
  110.     dec   rcx        ; Loop
  111.     jnz   @@dstgt        ;   until done
  112.     jmp sh @@sign        ; cf = 0
  113.  
  114. ; ----- Compute dst + src
  115. ;    cf = 0, df = 0
  116.     @alignn
  117. @@addn: mov   al, [rsi]     ; Get two digits of src
  118.     inc   rsi        ; Step src pointer
  119.     adc   al, @ES [rdi]    ; Add two digits of dst + cf
  120.     daa            ; Adjust to packed BCD format
  121.     stosb            ; Store al to destination
  122.     dec   rcx        ; Loop
  123.     jnz   @@addn        ;   until done
  124.     adc   ah, 00h        ; Set bit 0 in ah if overflow
  125.     ; jmp sh @@sign     ; Carry set by DAA if overflow
  126.  
  127. ; ----- Test for zero result, determine sign and return value
  128. ;    es:rdi -> dst's sign byte, df = 0
  129. ;    ah bit 7 = sign, bit 0 = overflow
  130. @@sign: mov   rcx, rbx        ; Get REP count
  131.     sub   rdi, rbx        ; Point to LSB
  132.     or    ah, 01000000b    ; Set Z bit in ah
  133.     and   rax, 0ff00h    ; Zero al (and high(eax) if 32-bit)
  134.     repz  scasb        ; See if result is zero
  135.     mov   al, 01000001b    ; Keep Z and C bits
  136.     jz sh @@sig2        ;   if zero
  137.     mov   al, 10000001b    ;   else keep S and C bits
  138. @@sig2: and   ah, al        ; Prepare for SAHF
  139.     mov   al, ah        ; Isolate sign
  140.     and   al, 80h        ;   bit in al
  141.     add   rdi, rcx        ; Point to dst's sign
  142.     stosb            ; Store sign
  143.     mov   al, ah        ; Copy C bit
  144.     and   al, 1        ;   to al
  145.     sahf            ; sf = bit 7, zf = bit 6, cf = bit 0
  146.     mov   ah, 0        ; Return flags and acc = carry
  147.     RET
  148. bcdAdd    endp
  149.  
  150.  
  151. ;//////////////////////////////////////////////////////////////////////
  152. ;//    Name    bcdSub
  153. ;//    Desc    Subtract two packed signed BCD numbers (dest -= src).
  154. ;//
  155. ;//
  156. ;//    Entry    Passed args
  157. ;//    Exit    Packed signed BCD difference returned to destination.
  158. ;//        Accumulator (and sf,zf,cf flags) determined:
  159. ;//        Acc = 0: No borrow
  160. ;//        Acc = 1: Borrow (overflow)
  161. ;//
  162. ;//    Note    Destination and source may be the same
  163.     @alignn
  164. bcdSub    proc
  165. arg    dstBCD    :dataptr, \    ; Addr of minuend (=result)
  166.     srcBCD    :dataptr, \    ; Addr of subtrahend
  167.     BCDsz    :@uint        ; Byte size of each BCD
  168. @uses    ds,es,rsi,rdi,rbx,rcx
  169. ;.
  170.     mov  ah, 80h        ; Set up to flip sign bit
  171.     jmp  join_        ; Subtraction is addition reversed
  172. bcdSub    endp
  173.  
  174.     END