home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / MOVBITS.ZIP / MOVBITS.ASM next >
Encoding:
Assembly Source File  |  1986-03-07  |  28.4 KB  |  542 lines

  1.         title   MOVBITS subroutine
  2.         page    80,132
  3.         .radix  10
  4. ;******************************************************************************
  5. ;*                                                                            *
  6. ;*    MOVBITS SUBROUTINE FOR USE IN TURBO PASCAL                              *
  7. ;*                                                                            *
  8. ;*    TURBO PASCAL DECLARATION-- procedure movbits(targseg,targoff,targbit,   *
  9. ;*      srcseg,srcoff,srcbit,nobits:integer); external 'movbits.bin';         *
  10. ;*                                                                            *
  11. ;*      targseg -- segment address of target area                             *
  12. ;*      targoff -- offset to first byte of target area                        *
  13. ;*      targbit -- starting bit number in target area, numbered from 0,       *
  14. ;*                 e.g., bit 0 is msb of byte at targseg:targoff, bit 15      *
  15. ;*                 is lsb of byte at targseg:targoff+1, etc.                  *
  16. ;*                                                                            *
  17. ;*      srcseg  -- segment address of source area                             *
  18. ;*      srcoff  -- offset to first byte of source area                        *
  19. ;*      srcbit  -- starting bit number in source area, numbered from 0,       *
  20. ;*                 same scheme as targbit                                     *
  21. ;*                                                                            *
  22. ;*      nobits  -- number of bits to move from source area to target area     *
  23. ;*                                                                            *
  24. ;*    ALTERNATE T. P. DECLARATION-- procedure movbits(targptr:byteptr;targbit:*
  25. ;*     integer;srcptr:byteptr;srcbit,nobits:integer); external 'movbits.bin'; *
  26. ;*                                                                            *
  27. ;*      targptr -- a variable declared of type ^byte loaded by the ptr func-  *
  28. ;*                 tion with the segment and offset values desired, or a call *
  29. ;*                 to the function addr with the desired area as the param-   *
  30. ;*                 eter, giving the target area address                       *
  31. ;*      targbit -- same as above                                              *
  32. ;*      srcptr  -- same as targptr for the source area                        *
  33. ;*      srcbit  -- same as above                                              *
  34. ;*      nobits  -- same as above                                              *
  35. ;*                                                                            *
  36. ;*    TYPICAL CALLING SEQUENCES--                                             *
  37. ;*      movbits(seg(videoram),ofs(videoram),133,seg(plotdata),ofs(plotdata),  *
  38. ;*       0,400);                                                              *
  39. ;*      movbits(addr(outfield),56,addr(infield),7,400);                       *
  40. ;*                                                                            *
  41. ;*    BREAK-DOWN OF CASES IN PARAMETERS--                                     *
  42. ;*                                                                            *
  43. ;*       case 0:  nobits is 0                                                 *
  44. ;*       case 1:  targbit and srcbit are multiples of 8                       *
  45. ;*       case 2:  targbit and srcbit are congruent modulo 8, i.e., they       *
  46. ;*                resolve to the same relative bit number in a byte           *
  47. ;*       case 3:  none of the above                                           *
  48. ;*                                                                            *
  49. ;*    CODING AND CHANGE LOG--                                                 *
  50. ;*                                                                            *
  51. ;*    15 OCT 1985 -- coding and initial testing finished                      *
  52. ;*    23 OCT 1985 -- alternate calling sequence tested and documented         *
  53. ;*     1 JAN 1986 -- correct typos in comments                                *
  54. ;*     2 JAN 1986 -- short jumps used where possible                          *
  55. ;*     4 JAN 1986 -- change page parameters and print on Oki 82.              *
  56. ;*                                                                            *
  57. ;******************************************************************************
  58.         subttl SYMBOLIC ASSIGNMENTS AND EQUATES
  59.         page
  60. NPARMS  =       7       ;number of parameters
  61. NBPUSH  =      24       ;number of bytes pushed upon entry (no. pushes * 2)
  62. ;
  63. ;
  64. ;
  65. wsw0    equ     word ptr[bp]    ;define location of work space word
  66. wsb0    equ     byte ptr[bp]    ;define location of work space bytes too
  67. wsb1    equ     byte ptr[bp+1]  ;note that these just share the same
  68.                                 ;area as the word above
  69. ;
  70. ;
  71. ;
  72. nobits  equ     word ptr[bp+NBPUSH+2]   ;define location of parameters on stack
  73. srcbit  equ     word ptr[bp+NBPUSH+4]   ;note that upon entry the return ip is
  74. srcoff  equ     word ptr[bp+NBPUSH+6]   ;on top of stack from push done by near
  75. srcseg  equ     word ptr[bp+NBPUSH+8]   ;call so the displacements start at +2
  76. targbit equ     word ptr[bp+NBPUSH+10]
  77. targoff equ     word ptr[bp+NBPUSH+12]
  78. targseg equ     word ptr[bp+NBPUSH+14]
  79. ;
  80. ;
  81. ;
  82.         subttl CODE AREA
  83.         page
  84. codeseg segment byte public 'CODE'
  85.         assume  cs:codeseg      ;dummy assume since cs will contain seg addr
  86.                                 ;of Turbo Pascal code and not codeseg
  87.         org     0h      ;start code at 0 since external procedures to be
  88.                         ;called from Turbo Pascal don't need a program
  89.                         ;segment prefix of 100h bytes
  90. ;
  91. ;       push things onto stack upon entry
  92. ;
  93. movbits000:
  94.         jmp     short movbits010        ;jump around id string
  95.         db      'movbits.bin'           ;identifying string constant
  96. movbits010:
  97.         push    ax      ;push general regs
  98.         push    bx
  99.         push    cx
  100.         push    dx
  101.         push    bp      ;push base pointer reg
  102.         push    si      ;push index regs
  103.         push    di
  104.         push    ds      ;push segment regs, except cs
  105.         push    ss
  106.         push    es
  107.         pushf           ;push processor flags
  108.         pushf           ;push it again to get some work space
  109. ;
  110. ;       set up the base pointer to access work space and parameter values
  111. ;       on the stack
  112. ;
  113.         mov     bp,sp   ;get current value of stack pointer into bp reg
  114. ;
  115. ;       now look at nobits to see if it is zero, if not then set up a few
  116. ;       regs with values needed by the other cases
  117. ;
  118.         mov     ax,nobits       ;get number of bits to move into ax
  119.         or      ax,ax           ;or with itself to set flag bits
  120.         jnz     movbits015      ;if it's not zero, then continue
  121.         jmp     mvbcase0        ;else it's zero, so we have case 0
  122. ;
  123. ;       clear direction flag, and load up segment and index regs to
  124. ;       address the effective source and target bytes
  125. ;
  126. movbits015:
  127.         cld                     ;make sure we auto-increment string ops
  128.         mov     ax,targseg      ;get seg addr of target
  129.         mov     es,ax           ;put it in es reg
  130.         mov     di,targoff      ;get offset to target into di
  131.         mov     ax,targbit      ;get target bit no.
  132.         mov     bx,ax           ;make a copy of it
  133.         and     bx,111b         ;make it modulo 8
  134.         mov     targbit,bx      ;and put it back into parameter area
  135.         mov     cl,3            ;load shift count
  136.         shr     ax,cl           ;divide by 8 to get displacement to byte
  137.                                 ;with the target bit
  138.         add     di,ax           ;add this extra offset to targoff
  139.         mov     ax,srcseg       ;get seg addr of source to ax
  140.         mov     ds,ax           ;put it in ds reg
  141.         mov     si,srcoff       ;get offset to source into si
  142.         mov     ax,srcbit       ;get source bit no.
  143.         mov     bx,ax           ;make a copy of it
  144.         and     bx,111b         ;make it modulo 8
  145.         mov     srcbit,bx       ;and put it back into parameter area
  146. ;
  147. ;       henceforth, targbit and srcbit are modulo 8 values, this is done
  148. ;       because after the addresses of the effective bytes are calculated
  149. ;       and put into the index regs, we don't need the 16 bit values but we
  150. ;       do require their modulo 8 values (often called the relative bit no.)
  151. ;
  152.         shr     ax,cl           ;divide by 8
  153.         add     si,ax           ;add this to srcoff
  154. ;
  155. ;       now look at the other parameters and determine which case we have
  156. ;
  157.         mov     ax,targbit      ;get target bit no. modulo 8
  158.         mov     bx,srcbit       ;get source bit no. modulo 8
  159.         cmp     al,bl           ;compare the two three bit values
  160.         je      movbits020      ;if they are equal, then decide between
  161.                                 ;case 1 and 2
  162.         jmp     mvbcase3        ;if they aren't equal, it must be case 3
  163. movbits020:
  164.         or      al,al           ;set flag bits
  165.         jz      mvbcase1        ;if it's zero, then we have case 1
  166.         jmp     short mvbcase2  ;else jump to case 2
  167. mvbcase0:
  168. ;
  169. ;       since nobits is zero, we have nothing to move
  170. ;
  171.         jmp     movbits999      ;return to caller via exit code
  172.         subttl  CASE 1--targbit and srcbit are multiples of 8
  173.         page
  174. mvbcase1:
  175. ;
  176. ;       if targbit and srcbit are multiples of 8, we can move bytes
  177. ;       without any shifting, the last byte moved may need masking
  178. ;
  179. ;
  180.         mov     cx,nobits       ;get no. bits to move
  181.         cmp     cx,8            ;compare it with 8
  182.         jl      movbits100      ;if moving less than 8 bits, it's a one byte
  183.                                 ;operation, so treat it as the last byte
  184.         shr     cx,1            ;else divide by 8 to get no. bytes to move
  185.         shr     cx,1
  186.         shr     cx,1
  187.         rep     movsb           ;move all whole bytes involved
  188.         mov     cx,nobits       ;get total no. bits to move back to cx
  189.         and     cl,111b         ;get no. of bits to move in last source byte
  190.         jz      movbits110      ;if it's zero, then we have moved all the
  191.                                 ;bytes with the rep movsb above, so return
  192. movbits100:
  193.         lodsb                   ;get last or only source byte to al reg
  194.         mov     ah,al           ;save it in ah
  195.         push    es              ;put target seg addr on stack
  196.         pop     ds              ;and transfer it to ds
  197.         mov     si,di           ;get destination index to si
  198.         lodsb                   ;get last or only target byte into al
  199.         mov     bx,0ffh         ;get a mask of 00ffh into bx
  200.         ror     bx,cl           ;build a zeroing mask byte in bh
  201.         and     ah,bh           ;clear low order bits in source byte
  202.                                 ;that will come from target byte
  203.         xor     bh,0ffh         ;invert the built up mask
  204.         and     al,bh           ;clear high order bits in target
  205.                                 ;byte will come from source byte
  206.         or      al,ah           ;or the two together
  207.         stosb                   ;store al to target area
  208. movbits110:
  209.         jmp     movbits999      ;return to caller via exit code
  210.         subttl  CASE 2--targbit and srcbit are congruent modulo 8
  211.         page
  212. mvbcase2:
  213. ;
  214. ;       if targbit and srcbit are congruent modulo 8 and not multiples of 8,
  215. ;       then the first byte will need masking, the intermediate bytes can be
  216. ;       moved without shifting bits, and the last byte may need masking
  217. ;
  218.         lodsb                   ;get the first source byte to al
  219.         mov     ah,al           ;save it in ah
  220.         push    ds              ;put ds on stack
  221.         push    es              ;and es too
  222.         pop     ds              ;and pop them back this way to swap them
  223.         pop     es
  224.         xchg    di,si           ;swap index regs
  225.         lodsb                   ;get the target byte to al, ah already
  226.                                 ;has corresponding source byte
  227.         push    ds              ;do this again
  228.         push    es              ;to swap ds and es back
  229.         pop     ds
  230.         pop     es
  231.         xchg    di,si           ;swap index regs back too
  232.         dec     di              ;decrement destination index so that it
  233.                                 ;points to target byte just loaded
  234. ;
  235. ;       clear source byte so as to preserve high order bits in first
  236. ;       target byte
  237. ;
  238.         mov     cx,srcbit       ;get source bit no. modulo 8
  239.         mov     bh,0ffh         ;get a mask of ffh into bh
  240.         shr     bh,cl           ;bring zeroes in from left
  241.         and     ah,bh           ;clear high order bits in source byte
  242. ;
  243. ;       see if all bits down to least significant will participate,
  244. ;       if not, then it's a partial move
  245. ;
  246.         mov     dx,8            ;load constant 8 = no. bits in a byte
  247.         sub     dx,cx           ;subtract source relative bit no. from 8
  248.                                 ;giving the no. bits that would need to
  249.                                 ;be moved to cover the whole byte
  250.         cmp     nobits,dx       ;compare with total no. bits to be moved
  251.         je      movbits200      ;if they are equal, then it's a one byte
  252.                                 ;move and whole byte is covered, so skip
  253.                                 ;the zeroing on right
  254.         jg      movbits210      ;if we're moving more bits than what
  255.                                 ;it takes to cover this byte, then jump
  256.                                 ;ahead to store this first byte and arm
  257.                                 ;for intermediate and last bytes
  258.         sub     dx,nobits       ;else calculate the no. bits that will be
  259.         mov     cl,dl           ;zeroed on right and put it in cl for shift
  260.         mov     ch,0ffh         ;get a mask of ffh into ch
  261.         shl     ch,cl           ;bring zeroes in on right
  262.         and     bh,ch           ;zero low order bits in preliminary mask
  263.         and     ah,bh           ;zero low order bits in source byte
  264. movbits200:
  265.         xor     bh,0ffh         ;invert the mask that prepared the source byte
  266.                                 ;on left and right
  267.         and     al,bh           ;zero bits in target byte that will come from
  268.                                 ;source byte
  269.         or      al,ah           ;or the haves and havenots together
  270.         stosb                   ;store al into target area
  271.         jmp     short movbits230;and leave
  272. ;
  273. ;       store a covered byte (all bits from targbit down to 7 on right are
  274. ;       moved) and adjust nobits
  275. ;
  276. movbits210:
  277.         xor     bh,0ffh         ;invert the mask that zeroed the source byte
  278.                                 ;on the left
  279.         and     al,bh           ;and use it to zero target byte on right
  280.         or      al,ah           ;or the haves and havenots together
  281.         stosb                   ;and store al in destination area
  282.         mov     cx,nobits       ;get total no. bits to move
  283.         sub     cx,dx           ;subtract the no. bits moved giving number
  284.                                 ;remaining to be moved
  285.         mov     nobits,cx       ;and put it back to memory
  286. ;
  287. ;       take care of the intermediate bytes
  288. ;
  289.         cmp     cx,8            ;compare no. bits remaining to be moved
  290.                                 ;with 8
  291.         jl      movbits220      ;if moving less than 8 bits, it's a one byte
  292.                                 ;operation, so treat it as the last byte
  293.         shr     cx,1            ;else divide by 8 to get no. bytes to move
  294.         shr     cx,1
  295.         shr     cx,1
  296.         rep     movsb           ;move all whole bytes involved
  297.         mov     cx,nobits       ;get remaining no. bits to move back to cx
  298.         and     cl,111b         ;get no. of bits to move in last source byte
  299.         jz      movbits230      ;if it's zero, then we have moved all the
  300.                                 ;bytes with the rep movsb above, so return
  301. movbits220:
  302.         lodsb                   ;else get last source byte to al reg
  303.         mov     ah,al           ;save it in ah
  304.         push    es              ;put target seg addr on stack
  305.         pop     ds              ;and bring it back to ds
  306.         mov     si,di           ;get destination index to si
  307.         lodsb                   ;get last target byte into al
  308.         mov     bx,0ffh         ;get a mask of 00ffh into bx
  309.         ror     bx,cl           ;bring ones in from left
  310.         and     ah,bh           ;clear low order bits in source byte
  311.                                 ;that will not be moved to target byte
  312.         xor     bh,0ffh         ;invert the built up mask
  313.         and     al,bh           ;clear high order bits in target byte
  314.                                 ;that will come from source byte
  315.         or      al,ah           ;or the two together
  316.         stosb                   ;store al to target area
  317. movbits230:
  318.         jmp     movbits999      ;return to caller
  319.         subttl  CASE 3--none of the above
  320.         page
  321. ;
  322. ;       since none of the above cases were met, we must shift all bytes moved
  323. ;       and first and last bytes all will need masking, intermediate bytes
  324. ;       in target will come from shifted words in source area
  325. ;
  326. ;       the technique used here is to shift the source area, byte by byte
  327. ;       as it is loaded into regs, so that it will be congruent to the
  328. ;       target byte
  329. ;
  330. mvbcase3:
  331.         mov     ax,srcbit       ;get source bit no. modulo 8
  332.         mov     bx,targbit      ;get target bit no. modulo 8
  333.         sub     bx,ax           ;subtract source relative bit no. from
  334.                                 ;target relative bit no. giving amount
  335.                                 ;to shift the source bytes; if positive,
  336.                                 ;then to right, if negative, then to left
  337.         jg      movbits300      ;if positive (bx > ax), then jump around
  338.                                 ;neg instruction; difference can not be 0
  339.         neg     bl              ;make the left shift amount positive
  340. movbits300:
  341.         mov     wsw0,bx         ;move the sign bit in bh and shift
  342.                                 ;amount in bl to work space word 0
  343.         lodsw                   ;get the first source byte pair to al,ah
  344.         xchg    ah,al           ;swap them because word is stored lsb,msb
  345.         dec     si              ;decrement source index so that the word
  346.                                 ;string slides along one byte at a time
  347.                                 ;rather than the two bytes that lodsw
  348.                                 ;implies
  349.         mov     cl,bl           ;put the shift amount into reg for shr ax,cl
  350.                                 ;or shl ax,cl below
  351.         test    bh,80h          ;test the sign bit of computed shift amount
  352.         jnz     movbits310      ;if a left shift is indicated, jump around
  353.                                 ;right shift code
  354.         shr     ah,cl           ;shift bits to right, bringing zeroes
  355.                                 ;into high order bits of ah
  356.         dec     si              ;for a right series, the first byte pair in
  357.                                 ;source area provides bits for both the first
  358.                                 ;and second bytes in target area, so decrement
  359.                                 ;once more to get back to it
  360.         jmp     short movbits320;jump around left shift code
  361. movbits310:
  362.         shl     ax,cl           ;shift bits to left so that bits from al
  363.                                 ;(the second byte) move up on bits in
  364.                                 ;ah from the right
  365. ;
  366. ;       ah contains a shifted source byte that now is congruent to target
  367. ;       byte, i.e, the bits to be moved from source are lined up to the
  368. ;       positions they will replace in the target; srcbit isn't the true
  369. ;       relative bit no. of source now, so we use targbit instead; this
  370. ;       same idea is used with the intermediate and last bytes
  371. ;
  372. movbits320:
  373.         push    ds              ;put ds on stack
  374.         push    es              ;and es too
  375.         pop     ds              ;and pop them back this way to swap them
  376.         pop     es
  377.         xchg    di,si           ;swap index regs
  378.         lodsb                   ;get the target byte to al
  379.         push    ds              ;do this again
  380.         push    es              ;to swap ds and es back
  381.         pop     ds
  382.         pop     es
  383.         xchg    di,si           ;swap index regs back too
  384.         dec     di              ;decrement destination index so that it
  385.                                 ;points to target byte just loaded
  386. ;
  387. ;       clear source byte so as to preserve high order bits in first
  388. ;       target byte
  389. ;
  390.         mov     cx,targbit      ;get target bit no. modulo 8
  391.         mov     bh,0ffh         ;get a mask of ffh into bh
  392.         shr     bh,cl           ;bring zeroes in from left
  393.         and     ah,bh           ;clear high order bits in source byte
  394. ;
  395. ;       see if all bits down to least significant will participate,
  396. ;       if not, then it's a partial move
  397. ;
  398.         mov     dx,8            ;load constant 8 = no. bits in a byte
  399.         sub     dx,cx           ;subtract target relative bit no. from 8
  400.                                 ;giving the no. bits that would need to
  401.                                 ;be moved to cover the whole byte
  402.         cmp     nobits,dx       ;compare with total no. bits to be moved
  403.         je      movbits330      ;if they are equal, then it's a one byte
  404.                                 ;move and whole byte is covered, so skip
  405.                                 ;the zeroing on right
  406.         jg      movbits340      ;if we're moving more bits than what
  407.                                 ;it takes to cover this byte, then jump
  408.                                 ;ahead to store this first byte and arm
  409.                                 ;for intermediate and last bytes
  410. ;
  411. ;       we arrive here if nobits<8-targbit (the no. needed to cover the
  412. ;       whole byte down to bit 7)
  413. ;
  414.         sub     dx,nobits       ;else calculate the no. bits that will be
  415.         mov     cl,dl           ;zeroed on right and put it in cl for shift
  416.         mov     ch,0ffh         ;get a mask of ffh into ch
  417.         shl     ch,cl           ;bring zeroes in on right
  418.         and     bh,ch           ;zero low order bits in preliminary mask
  419.         and     ah,bh           ;zero low order bits in source byte
  420. movbits330:
  421.         xor     bh,0ffh         ;invert the mask that prepared the source byte
  422.                                 ;on left and right
  423.         and     al,bh           ;zero bits in target byte that will come from
  424.                                 ;source byte
  425.         or      al,ah           ;or the haves and havenots together
  426.         stosb                   ;store al into target area
  427.         jmp     movbits360      ;and leave the scene
  428. ;
  429. ;       store a covered byte and adjust nobits
  430. ;
  431. movbits340:
  432.         xor     bh,0ffh         ;invert the mask that zeroed the source byte
  433.                                 ;on the left
  434.         and     al,bh           ;and use it to zero target byte on right
  435.         or      al,ah           ;or the haves and havenots together
  436.         stosb                   ;and store al in destination area
  437.         mov     cx,nobits       ;get total no. bits to move
  438.         sub     cx,dx           ;subtract the no. bits moved giving number
  439.                                 ;remaining to be moved
  440.         mov     nobits,cx       ;and put it back to memory
  441. ;
  442. ;       take care of the intermediate bytes
  443. ;
  444.         cmp     cx,8            ;compare no. bits remaining to be moved
  445.                                 ;with 8
  446.         jl      movbits350      ;if moving less than 8 bits in last byte,
  447.                                 ;skip the intermediate move loops
  448.         shr     cx,1            ;else divide by 8 to get no. bytes to move
  449.         shr     cx,1
  450.         shr     cx,1
  451.         mov     dl,wsb0         ;get the calculated shift amount, left or
  452.                                 ;right as we are about to determine
  453.         test    wsb1,80h        ;test sign bit of calculated shift amount
  454.                                 ;to determine if it's a left or right series
  455.         jnz     movbits346      ;jump around right shift code if bit is 1
  456. movbits343:
  457.         mov     bx,cx           ;make a copy of loop counter
  458.         lodsw                   ;get a byte pair from source area
  459.         xchg    ah,al           ;swap them because word is stored lsb,msb
  460.         dec     si              ;move pair along by one, not two, bytes
  461.         mov     cl,dl           ;get shift amount back
  462.         shr     ax,cl           ;shift to right into al
  463.         stosb                   ;put byte in al away in target area
  464.         mov     cx,bx           ;get loop counter back
  465.         loop    movbits343      ;loop until all intermediate bytes have been
  466.                                 ;moved
  467.         jmp     short movbits348;jump around left shift code
  468. movbits346:
  469.         mov     bx,cx           ;make a copy of loop counter
  470.         lodsw                   ;get a byte pair from source area
  471.         xchg    ah,al           ;swap them
  472.         dec     si              ;move pair along by one, not two, bytes
  473.         mov     cl,dl           ;get shift amount back
  474.         shl     ax,cl           ;shift to left into ah
  475.         mov     al,ah           ;put shifted source byte into al for store
  476.         stosb                   ;put byte in al away in target area
  477.         mov     cx,bx           ;get loop counter back
  478.         loop    movbits346      ;loop until all intermediate bytes have been
  479.                                 ;moved
  480. movbits348:
  481.         mov     cx,nobits       ;get no. bits to move back to cx
  482.         and     cx,111b         ;calculate no. bits to move out of last
  483.                                 ;source byte
  484.         jz      movbits360      ;if it's zero, then we have moved all the
  485.                                 ;bytes with the code above, so return
  486. movbits350:
  487.         mov     dl,wsb0         ;else get the calculated shift amount to dl
  488.         xchg    cl,dl           ;cl gets source shift amount and dl gets
  489.                                 ;no. bits to move in last byte
  490.         lodsw                   ;get last source byte pair to al,ah
  491.         xchg    ah,al           ;swap them since they are stored lsb,msb
  492.         test    wsb1,80h        ;test sign bit of calculated shift amount
  493.                                 ;to determine if it's a left or right series
  494.         jnz     movbits352      ;jump around right shift code if bit is 1
  495.         shr     ax,cl           ;shift to right into al
  496.         mov     ah,al           ;put it in ah for later
  497.         jmp     short movbits354;jump around left shift code
  498. movbits352:
  499.         shl     ax,cl           ;shift to left into ah
  500. movbits354:
  501.         mov     cl,dl           ;cl now gets count of no. ones to bring
  502.                                 ;in from left in mask built below
  503.         push    es              ;put target seg addr on stack
  504.         pop     ds              ;and bring it back to ds
  505.         mov     si,di           ;get destination index to si
  506.         lodsb                   ;get last target byte into al
  507.         mov     bx,0ffh         ;get a mask of 00ffh into bh,bl
  508.         ror     bx,cl           ;bring some ones in from left
  509.         and     ah,bh           ;clear low order bits in source byte
  510.                                 ;that will come from target byte
  511.         xor     bh,0ffh         ;invert the built up mask
  512.         and     al,bh           ;clear high order bits in target byte
  513.                                 ;that will come from source byte
  514.         or      al,ah           ;or the two together
  515.         stosb                   ;store al to target area
  516. movbits360:
  517.         jmp     short movbits999;return to caller
  518.         subttl  RETURN TO CALLER
  519.         page
  520. ;
  521. ;       pop things back from stack before exit
  522. ;
  523. movbits999:
  524.         popf            ;pop the work space word off of stack
  525.         popf            ;pop the flags
  526.         pop     es      ;pop segment regs
  527.         pop     ss
  528.         pop     ds
  529.         pop     di      ;pop index regs
  530.         pop     si
  531.         pop     bp      ;pop base pointer
  532.         pop     dx      ;pop general regs
  533.         pop     cx
  534.         pop     bx
  535.         pop     ax
  536.         ret     NPARMS*2;remove arguments from stack and do a near return
  537. ;
  538. ;
  539. ;
  540. codeseg ends
  541.         end     movbits000
  542.