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

  1.     title    BCDASM -- Copyright 1997, Morten Elling
  2.     subttl    Perform a digit left-shift (MUL 10^n) on a packed BCD
  3.  
  4.     include    model.inc
  5.     include    modelt.inc
  6.     include    bcd.ash
  7.  
  8.     @CODESEG
  9.  
  10. ;//////////////////////////////////////////////////////////////////////
  11. ;//    Name    bcdShl
  12. ;//    Desc    Perform a digit left-shift of a packed signed BCD.
  13. ;//
  14. ;//
  15. ;//    Entry    Passed args
  16. ;//    Exit    Packed signed BCD returned to destination.
  17. ;//        Accumulator (and cf,zf flags) determined:
  18. ;//             Acc = 0: Result is zero (zf=1)
  19. ;//        Acc > 0: Result is non-zero (zf=0)
  20. ;//
  21. ;//        If any significant digits were shifted out
  22. ;//        of the high-order, cf=1, else cf=0
  23. ;//        (sign and overflow flags should be ignored).
  24. ;//
  25. ;//    Note    A 10-byte BCD holds 18 BCD digits ( 2*(10-1) ).
  26. ;//
  27. ;//    Note    This procedure shifts one digit, i.e. one nibble, 
  28. ;//        per shift count effectively performing a
  29. ;//        MUL 10-to-the-n'th-power operation.
  30. ;//        Zeros are shifted into the low-order. The sign of
  31. ;//        the destination is changed only if the result is
  32. ;//        zero. If the shift count is larger than or equals
  33. ;//        the number of digits in the BCD, the result will
  34. ;//        be zero.
  35.  
  36. bcdShl    proc
  37. arg    dstBCD    :dataptr, \    ; Addr of BCD
  38.     dstsz    :@uint, \    ; Byte size of BCD
  39.     count    :@uint        ; No. of BCD digits to shift
  40. @uses    ds,es,rsi,rdi,rbx,rcx,rdx
  41. ;.
  42. ; ----- Load registers. Instead of a local variable, the AH 
  43. ;    register is used to flag if any significant digits 
  44. ;    are shifted out of the high-order. The 80x86 SHL
  45. ;    instruction, however, flags only the last bit shifted.
  46.  
  47.     @cld            ; String ops forward
  48.     @LDS  rsi, [dstBCD]
  49.     @LES  rdi, [dstBCD]
  50.     mov   rdx, [count]
  51.     mov   rbx, [dstsz]
  52.     dec   rbx        ; # bytes, excl. sign byte
  53.     mov   ah, 00h
  54.  
  55. ; ----- Handle special cases
  56.     test  rdx, rdx         ; If under-sized shift,
  57.     jz sh @@chkz        ;   check for zero result
  58.     mov   rcx, rdx        ; Shift count
  59.     shr   rcx, 1        ; Make # bytes
  60.     jz sh @@odd        ; If zero, shift count = 1
  61.     cmp   rcx, rbx        ; If over-sized shift,
  62.     jae sh @@clear        ;   zero-fill
  63.  
  64. ; ----- Shift the even digit pairs
  65.     add   rdi, rbx
  66.     dec   rdi        ; Point to byte before sign
  67.     mov   rsi, rdi
  68.     sub   rsi, rcx        ; Point to source
  69.     push  rcx        ; Save count/2
  70.     neg   rcx        ; - Count/2
  71.     add   rcx, rbx        ; + Field width = # bytes to shift
  72.     push  rcx
  73.     push  rdi
  74.     sub   al, al        ; Zero al
  75.     std            ; Auto-decrement index reg.s
  76.     repz  scasb        ; Determine 
  77.     sbb   ah, ah        ;   significance flag
  78.     pop   rdi
  79.     pop   rcx
  80.     rep   movsb        ; Shift left (rsi < rdi)
  81.     pop   rcx        ; Count/2 = # bytes to zero
  82.     rep   stosb        ; Zero low-order of number
  83.     inc   rdi        ; Point to LSB
  84.     cld            ; Auto-increment index reg.s
  85.  
  86. ; ----- Prepare for odd digit
  87.     shr   rdx, 1        ; Is there an odd digit?
  88.     jnc sh @@chkz         ; No, see if result is zero
  89.     add   rdi, rdx        ; Point index reg.s
  90.     mov   rsi, rdi        ;   to target
  91.     mov   rcx, rdx        ; Get # bytes shifted
  92.     neg   rcx        ; Negate
  93. @@odd:    add   rcx, rbx        ; = # bytes to 'odd-shift'
  94.  
  95. ; ----- Shift the odd digit
  96.     sub   dl, dl        ; Zero dl
  97.     mov   dh, ah        ; Temporary signif. flag
  98. @@lt:    lodsb            ; Get a byte
  99.     or    dh, al        ; Update signif. flag
  100.     @shl  rax, 4        ; Shift acc left one nibble
  101.     or    al, dl        ; Combine with prev. digit
  102.     stosb            ; Store al to destination
  103.     mov   dl, ah        ; Save high-order
  104.     and   dl, 0fh        ;   for next loop
  105.     loop  @@lt        ; Loop until done
  106.     sub   rdi, rbx        ; Point to LSB
  107.     mov   ah, dh        ; Copy signif. flag to ah
  108.  
  109. ; ----- Check if result is zero
  110. @@chkz:    ; rdi -> LSB
  111.     mov   rcx, rbx        ; REP count
  112.     sub   al, al        ; Zero al
  113.     repz  scasb        ; See if all zeros (cf=0 if zero)
  114.     rcr   al, 1        ; Set to 80h if result non-zero
  115.     add   rdi, rcx        ; Point to sign byte
  116.     jmp sh @@sign
  117.  
  118. ; ----- Shift count > # digits: zero-fill
  119. @@clear: ; rdi -> LSB
  120.     mov   rcx, rbx        ; REP count
  121.     sub   al, al        ; Zero al
  122.     repz  scasb        ; See if all zeros
  123.     sbb   ah, ah        ; ah = significance flag
  124.     add   rdi, rcx        ; Point
  125.     sub   rdi, rbx        ;   back to LSB
  126.     mov   rcx, rbx        ; REP count
  127.     rep   stosb        ; Whip it
  128.  
  129. ; ----- Determine sign and return value
  130. @@sign:    ; rdi -> sign byte
  131.     ; al = 0 if result zero, else 80h
  132.     ; ah = significance flag (0 or > 0)
  133.     neg   ah        ; If zero, 
  134.     sbb   dl, dl        ;   set dl 0, else 0FFh
  135.     and   @ES [rdi], al    ; Clear sign bit if appropriate
  136.     rol   al, 1        ; Set acc 0 or 1
  137.     and   rax, 1        ; Determine acc and zero flag
  138.     ror   dl, 1        ; Determine carry flag
  139.     RET            ; Return acc, zf and cf
  140. bcdShl    endp
  141.  
  142.     END