Okay, you UUencoder types should get a kick out of this.
Quoted in it's entirety...  8-)

-------------------------------------------------------


From jtucker@byron.apana.org.au
Date: Sun, 18 Jun 1995 21:15:52 +0930
From: Jim Tucker <jtucker@byron.apana.org.au>
To: jvahn@short.circuit.com
Subject: Mode 91 encoder/decode

James:

I finally found inspiration to translate the mod91 encoder Terje
Mathisen sent me in Norwegian- a language we can all understand ;).

Here are the working models. The encoder is slightly complex but the
payoff if is the decoder (which is the important bit) is tiny, efficient
and complies with the FTS* standard.

The encoded data can have eol code or blank spaces anywhere. UNIX or 
Mac line endings okay too. Or you can have no line endings at all!

The only thing it will not like is a missing last line. This contains 
the terminating char " (ASCII 34) followed by the number of bytes
to ignore asciified (+'0'). Ideally, I would store a size in the first n 
bytes of data. This would add to the size of the decoder.

The expansion is 1.234 (curious number that). In the real world 
including crlf it is slightly more than 1.25:

       40,000 uue    => 56006 bytes
       40,000 base91 => 50774 bytes




* Fault Tolerant Software

.............. clip ..................................................

; BASE91 DECODER
; BAS91DEC <INFILE >OUTFILE

start:	mov	ah,3Fh		; read from stdin
	xor	bx,bx
	mov	dx,buffer
	push	dx		; save DX for writing
	mov	cx,65000
	int	21h

	mov	si,buffer	; start of data
        mov     di,si		; write over input
	cld
        xor     cx,cx
	mov	cl,8

top:	lodsb
        sub	al,34
        jb	top		; ignore
        jz	done		; eof
        dec	ax
        mov	ah,91
        mul	ah
        xchg    ax,dx           ; Save first 6.5 bits
        xor     ax,ax

next:	lodsb
        sub	al,35
        jb	next
        add	ax,dx           ; Add together to 13 bits
        stosb                   ; Save low 8
        xor     al,al
        shr     ax,cl
        or      ch,al
        sub     cl,5
	jg	top
        mov     [di],ch
        inc     di
        mov     ch,ah
	add	cl,8
        jmp	top

done:	pop	dx		; begin data
	mov	cx,di		; last byte read
	sub	cx,dx		; bytes read
	lodsb			; bytes to ignore
	sub	al,'0'		; ascii correction
	cbw
	sub	cx,ax		; bytes to write
	mov	ah,40h		; write
	mov	bx,1		; stdout
	int	21h
	mov	ax,4C00h
	int	21h

buffer equ $

.............. clip ..................................................

; BASE91 ENCODER
; BAS91ENC <INFILE >OUTFILE

	jmp	start

MAXSIZE EQU 52500

ilen		dw	?	; size of input
out_pointer	dw	0	; pointer
char_count	db	4       ; for crlf
ignore_byte	db	?

start:	mov	bx,sp		; use 64K for this
	mov	cl,4
	shr	bx,cl
	inc	bx
	mov	ah,4Ah
	int	21h		; should jc error

	mov	bx,1000h	; allocate 64K segment
	mov	ah,48h		; for output
	int	21h		; should jc error
	mov	es,ax		; output goes to es

	mov	ah,3Fh		; read stdin
	xor	bx,bx
	mov	dx,buffer
	mov	cx,MAXSIZE
	int	21h
	mov	cx,buffer	; target
	add	cx,ax		; add bytes read
	mov	ilen,cx

; We always read 13 (maybe past eof) so we tell the decoder how many 
; bytes to ignore.

	mov	bx,13		; calc # bytes to ignore
	cwd			; clears dx
	idiv	bx
	mov	al,dl		; mod 13
	or	al,al		; any bytes left?
	jz	>l1		; no
	sub	bl,al		; calc how many
	mov	al,bl
L1:	add	al,'0'		; asciify
	mov	ignore_byte,al	; save it for now
	mov	bx,buffer	; initialize bx

;-----------------------------------------------------------------------
;

enc_loop:

; a = i[2]
; word ptr [0] = i[0] + ((a & 0x1f) << 8);
    
        mov     al,[bx+2]	; a = i[2]
        mov     ah,0
        mov     si,ax

        and     ax,31
        mov     cl,8
        shl     ax,cl
        mov     dl,[bx]
        mov     dh,0
        add     dx,ax
        mov     word ptr [enc],dx

; b = i[5]
; word ptr [1] = i[1] + ((a & 0xe0) << 3) + ((b & 0x3) << 11);

	mov     al,[bx+5]	; b = i[5]
        mov     ah,0
        mov     di,ax

        mov     al,[bx+1]
        mov     ah,0
        mov     dx,si
        and     dx,0E0h
        shl     dx,1
        shl     dx,1
        shl     dx,1
        add     ax,dx
        mov     dx,di
        and     dx,3
        mov     cl,11
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+2],ax

; word ptr [2] = i[3] + ((b & 0x7c) << 6);

        mov     al,[bx+3]
        mov     ah,0
        mov     dx,di
        and     dx,124
        mov     cl,6
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+4],ax
   
; a = i[7];
; word ptr [3] = i[4] + ((b & 0x80) << 1) + ((a & 0xf) << 9);

        mov     al,[bx+7]       ; a = i[7]
        mov     ah,0
        mov     si,ax

        mov     al,[bx+4]
        mov     ah,0
        mov     dx,di
        and     dx,128
        shl     dx,1
        add     ax,dx
        mov     dx,si
        and     dx,15
        mov     cl,9
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+6],ax
 
; b = i[10];
; word ptr [4] = i[6] + ((a & 0xf0) << 4) + ((b & 0x1) << 12);

        mov     al,[bx+10]      ; b = i[10]
        mov     ah,0
        mov     di,ax

        mov     al,[bx+6]
        mov     ah,0
        mov     dx,si
        and     dx,240
        mov     cl,4
        shl     dx,cl
        add     ax,dx
        mov     dx,di
        and     dx,1
        mov     cl,12
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+8],ax

; word ptr [5] = i[8] + ((b & 0x3e) << 7);

	mov     al,[bx+8]
        mov     ah,0
        mov     dx,di
        and     dx,62
        mov     cl,7
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+10],ax
  
; a = i[12];
; word ptr [6] = i[9] + ((b & 0xc0) << 2) + ((a & 0x7) << 10);

        mov     al,[bx+12]      ; a = i[12]
        mov     ah,0
        mov     si,ax

	mov     al,[bx+9]
        mov     ah,0
        mov     dx,di
        and     dx,192
        shl     dx,1
        shl     dx,1
        add     ax,dx
        mov     dx,si
        and     dx,7
        mov     cl,10
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+12],ax

; word ptr [7] = i[11] + ((a & 0xf8) << 5);

	mov     al,[bx+11]
        mov     ah,0
        mov     dx,si
        and     dx,248
        mov     cl,5
        shl     dx,cl
        add     ax,dx
        mov     word ptr [enc+14],ax
  
;-----------------------------------------------------------------------
;    
; read 8 bytes and write 16 to es:di   

	push	bx
	mov	si,OFFSET enc
	mov	di,out_pointer
	mov	cx,8
    
; *o++ = a / 91 + 35;
    
L1:	lodsw
	push	ax
	mov     bx,91
        cwd     
        idiv    bx
        add     al,35
	stosb
    
; *o++ = a % 91 + 35;
    
	pop	ax
        mov     bx,91
        cwd     
        idiv    bx
	mov	al,dl
	add     al,35
	stosb
	loop	l1

	dec	char_count		; crlf
	jnz	no_ch
	mov	ax,0A0Dh
	stosw
	mov	al,4
	mov	char_count,al

no_ch:	mov	out_pointer,di
	pop	bx
	add	bx,13			; bump input pointer
	cmp	bx,word ptr ilen	; read to end?
	jae	done			; yes
	jmp	enc_loop

;-----------------------------------------------------------------------

done:	mov	di,out_pointer          ; eof char
	mov	al,'"'
	stosb
	mov	al,ignore_byte          ; for decoder                  
	stosb
	mov	ax,0A0Dh
	stosw

	mov	cx,di                   ; write stdout
	xor	dx,dx
	mov	ah,40h
	mov	bx,1
	push	es
	pop	ds
	int	21h
	mov	ax,4C00h
	int	21h

enc	equ	$
	dw	8 dup (0)

buffer	equ $

[end.of.it]


From jtucker@byron.apana.org.au
Date: Wed, 21 Jun 1995 12:27:44 +0930
From: Jim Tucker <jtucker@byron.apana.org.au>
To: jvahn@short.circuit.com
Subject: Base 91 (more asm source)

James: You know that Base 91 stuff I translated from C ? It does an 
awful lot of messing around. Well, I sent it to Terje Mathisen who wrote 
the C code. He sent me this. The moral, of course, it don't do maths
when you can use a table. You might like to add this to the other stuff.

.... clip.............................................................

; Table giving offset to low extra bits, high extra bits, and low byte:
encode_table label byte
db 2,2,0, 2,5,1, 5,5,3, 5,7,4, 7,10,6, 10,10,8, 10,12,9, 12,12,11

encode_block:
  mov cx,91 * 256               ; CH has divider, CL shift count (= 0)
  mov bx,0

next_outer_loop:
  mov bp,OFFSET encode_table
  mov dx,8                      ; Generate 8 pairs of output!

next_inner_loop:
  mov bl,[bp]                   ; Offset to low extra bits
  mov al,[si+bx]
  mov bl,[bp+1]                 ; Ditto for high part
  mov ah,[si+bx]
  mov bl,[bp+2]
  add bp,3                      ; Point to next 3-byte offset ptr block
  shl ax,cl                     ; shift into position
  add cl,3                      ; adjust shift count for next iteration
  and ah,1fh                    ; and keep 5 low bits of AH
  and cl,7                      ; Must be in 0 to 7 range!
  mov al,[si+bx]                ; Retrieve AL directly
  div ch                        ; Divide AX by 91
  add ax,2323h                  ; Add 35 to AL and AH
  stosw                         ; and save (already in proper order!)
  dec dx                        ; More pairs?
   jnz next_inner_loop

  add si,13
  cmp si,bytes_to_read
   jb next_outer_loop
   ... done

[.sig]
