Listing 4 Assembly language implementation of scale_fax_line

;************************************************
;* function: int scale_fax_line(unsigned char *dest, unsigned char *src)
;* NOTE: The C code uses right rotates, this uses left rotates
;*       cuz they are easier in assembly. The direction is not
;*       important just as long as you are consistent. ;************************************************/
vector_end_line:                ;short jump way station
      jmp  end_line
public scale_fax_line
scale_fax_line proc uses ds si di, dest: near ptr byte, src: near ptr byte
;int scale_fax_line(unsigned char *dest, unsigned char *src)
;   {
;   int y_repeat,x_repeat,i,bit;
;   unsigned int accum;
;   unsigned char byte;
;   unsigned char *start;
;   ROTATOR rotator;

      assume ds:nothing
   ;* get line repeat value and rotate to next */
;   y_repeat = y_base + (y_rotator & 0x01);
;   _ror(y_rotator);
;   if (y_repeat)
;      {
      mov    ax,word ptr cs:y_rotator
      add    ax,ax
      rcl    word ptr cs:y_rotator+2,1
      adc    ax,0
      mov    word ptr cs:y_rotator,ax
      and    ax,1
      add    al,cs:y_base
      jnz    line_ok
      jmp    no_line
line_ok:
      push   bp
      push   ax
   ;* if anything to do */
      mov    si,ds                  ;large model data use lds and les
      mov    es,si
      mov    si,src
      mov    di,dest
;      rotator = x_rotator;
      mov    bx,word ptr cs:x_rotator
      mov    dx,word ptr cs:x_rotator+2
;      for (i = source_width, accum=1, start=dest ; i > 0; i--, src++)
      mov    bp,cs:source_width
      mov    ah,1
      push   di
;          {    ;* each byte in the source line */
byte_loop:
      dec    bp
      js     vector_end_line
      lodsb
;          if (*src)
      or      al,al
      jz      all_white
;              { ;* if it has black bits */
;              for (bit=8, byte=*src ; bit > 0; bit--)
;                  { ;* for each bit in the byte */
;                  x_repeat = x_base + (rotator & 1);
;                  _ror(rotator);     ;* get repeat count and rotate */
*                  while (x_repeat--)
*                      {              ;* for each repeat */
;                      accum << = 1;  ;* copy bit into accumulator */
;                      accum += ((byte & 0x80) ! = 0);
;                      if (accum & 0x100)
;                          {      ;* output a byte and reset sentinel */
;                          *dest++ = (unsigned char) accum;
;                          accum = 1;
;                          }
;                      }
;                  byte << = 1;
      mov    cl,8
bit_loop:
      xor    ch,ch
      add    bx,bx
      adc    dx,dx
      adc    ch,0
      add    bl,ch
      add    ch,cs:x_base
      or     ch,ch
      jz     bit_next
bit_repeat:
      cmp    al,80h
      cmc
      adc    ah,ah
      jc     bit_update
repeat_next:
      dec    ch
      jnz    bit_repeat
bit_next:
      add    al,al
      dec    cl
      jnz    bit_loop
      jmp    short byte_loop
bit_update:
      xchg    al,ah
      stosb
      xchg    al,ah
      mov     ah,1
      jmp     short repeat_next
;                  }
;              }
;          else
;              {  ;* no black bits, just spin it out. */
all_white:
            ;  * how many repeats? */
;             x_repeat = bit_repeat_count + ((rotator & Oxff) > bit_repeat_ pattern);
      xor    cx,cx
      cmp    cs:bit_repeat_pattern,dh
      adc    cx,cs:bit_repeat_count
            ;* rotate by 8 */
;             rotator = (rotator << (PRECISION-8)) | (rotator >> 8);
      xchg   bl,bh
      xchg   bl,dl
      xchg   bl,dh
            ;* do it */
;             while (x_repeat--)
;                 {
;                 accum << = 1;
;                 if (accum & 0x100)
;                     {
;                     *dest++ = (unsigned char) accum;
;                     accum = 1;
;                     }
;                 }
      jcxz  byte_loop
white_loop:
      add   ax,ax
      jc    white_update
      loop  white_loop
      jmp   byte_loop
white_update:
      xchg  al,ah
      stosb
      xchg  al,ah
      mov   ah,1
      loop  white_loop
      jmp   byte_loop
;            }
;          }
;      if (accum > 1)
;          {                      ;* handle fragment */
;          while ((accum & 0x100) == 0)
;              accum <<= 1;
;          *dest++ = (unsigned char) accum;
;          }
end_line:
      cmp   ah,1
      jbe   no_fragment
fragment_loop:
      add    ah,ah
      jnc    fragment_loop
      stosb
no_fragment:
;       while (dest < start + FAX_WIDTH)
;           {                      ;* white out tail */
;           *dest++ = 0;
;           }
;      }
      pop  ax
      sub  ax,di
      add  ax,FAX_WIDTH
      jle  no_tail
      mov  cx,ax
      xor  ax,ax
      shr  cx,1
      rep  stosw
      adc  cx,0
      rep  stosb
no_tail:
;   return y_repeat;
      pop      ax
      pop      bp
no_line:
      ret
;   }
scale_fax_line endp

; End of File