;+ ; ; Utility to convert to/from MIME BASE64 encoding. ; ; 04/22/97 JMBW Created. ; ;- .radix 8 ; lf= 12 cr= 15 ; ibufl= 16384d ;size of input buf obufl= 16384d ;size of output buf ; code segment assume cs:code org 100h ; start: cld ;DF=0 call from int 20h ;+ ; ; Convert from BASE64 to binary. ; ;- from: mov ax,-1 ;init prev chars mov dx,ax mov di,offset obuf ;point at output buf from1: call load ;get more jcxz from10 ;EOF xor bh,bh ;clear high half from2: mov bl,[si] ;get a byte inc si ;skip it mov bl,ds:from64[bx] ;translate test bl,bl ;negative? js from5 ;yes from3: mov dh,dl ;ripple up mov dl,ah mov ah,al mov al,bl cmp dh,-1 ;is that 4 chars? jne from6 ;yes, store from4: loop from2 ;handle rest of buffer jmp short from1 ;go refill buffer from5: inc bl ;-1 or -2? jz from4 ;-1, ignore jmp short from3 from6: ; store 4 chars as 3 bytes cmp dh,-2 ;can't have padding except as last 1-2 chars je from9 cmp dl,-2 je from9 sal dl,2 ;squish high order together sal dx,2 mov [di],dh ;save 1st char inc di cmp ah,-2 ;padding OK as 3rd char if 4th char is also je from8 sal dx,2 ;make space or dl,ah sal dx,6 ;left-justify mov [di],dh ;save 2nd char inc di cmp al,-2 ;padding as last char? je from7 or al,dl ;compose 3rd char mov [di],al ;save inc di from7: mov ax,-1 ;reinit prev chars mov dx,ax cmp di,offset obuf+obufl-3 ;almost full? jb from4 ;loop if not call flush ;flush output buffer jmp short from4 ;loop from8: cmp al,-2 ;is 4th char also padding? je from7 ;yes from9: mov dx,offset fmterr ;format error jmp punt ;die ;;; once we accept a '=' char there should be no more non-padding chars ;;; (set a flag on -2 accepted above) from10: ; EOF, see if we owe any chars cmp al,-1 ;anything stored? je from12 ;no inc cx ;pretend we got one char so we'll loop from11: cmp dh,-1 ;should be multiple of 4 chars jne from6 ;it is, good mov dh,dl ;left-justify mov dl,ah mov ah,al mov al,-2 ;pad with "=" jmp short from11 from12: call flush ;flush final buf ret ;+ ; ; Load next bufferful of file data. ; ; ax,dx preserved ; si returns ptr to data ; cx returns byte count (0=EOF) ; ;- load: push ax ;save push dx mov dx,offset ibuf ;point at buf mov cx,ibufl ;length xor bx,bx ;STDIN mov ah,3Fh ;func=read int 21h jc load1 ;failed mov si,dx ;point at it mov cx,ax ;get actual length pop dx ;restore pop ax ret load1: mov dx,offset rderr ;read error jmp short punt ;+ ; ; Flush output buf. ; ; di OBUF ptr (reset on return) ; ax,cx,dx preserved ; ;- flush: push ax ;save push cx push dx mov dx,offset obuf ;pt at buf sub di,dx ;find length jz flush1 ;0, skip mov cx,di ;copy mov bx,0001h ;STDOUT mov ah,40h ;func=write int 21h jc flush2 ;error flush1: mov di,dx ;reset ptr pop dx ;restore pop cx pop ax ret flush2: mov dx,offset wrerr ;write error ;jmp short punt ;+ ; ; Fatal error. ; ; dx ptr to .ASCIZ error message ; ;- punt: mov di,dx ;copy ptr xor al,al ;search for zero repz scasb ;(will always succeed) dec di ;point at it sub di,dx ;find length mov cx,di ;copy mov bx,0002h ;STDERR mov ah,40h ;func=write int 21h mov ax,4C01h ;func=punt int 21h ; ; Table to translate from BASE64 to binary. Values: ; 00-77 6-bit binary value ; -1 invalid character ; -2 "=", padding char (fills last 0-2 chars for partial 24-bit sequence) ; from64 db -1,-1,-1,-1,-1,-1,-1,-1 ;^@ ^A ^B ^C ^D ^E ^F ^G db -1,-1,-1,-1,-1,-1,-1,-1 ;^H ^I ^J ^K ^L ^M ^N ^O db -1,-1,-1,-1,-1,-1,-1,-1 ;^P ^Q ^R ^S ^T ^U ^V ^W db -1,-1,-1,-1,-1,-1,-1,-1 ;^X ^Y ^Z ^[ ^\ ^] ^^ ^_ db -1,-1,-1,-1,-1,-1,-1,-1 ;SP ! " # $ % & ' db -1,-1,-1,76,-1,-1,-1,77 ;( ) * + , - . / db 64,65,66,67,70,71,72,73 ;0 1 2 3 4 5 6 7 db 74,75,-1,-1,-1,-2,-1,-1 ;8 9 : ; < = > ? db -1,00,01,02,03,04,05,06 ;@ A B C D E F G db 07,10,11,12,13,14,15,16 ;H I J K L M N O db 17,20,21,22,23,24,25,26 ;P Q R S T U V W db 27,30,31,-1,-1,-1,-1,-1 ;X Y Z [ \ ] ^ _ db -1,32,33,34,35,36,37,40 ;` a b c d e f g db 41,42,43,44,45,46,47,50 ;h i j k l m n o db 51,52,53,54,55,56,57,60 ;p q r s t u v w db 61,62,63,-1,-1,-1,-1,-1 ;x y z { | } ~ RO db 128d dup(-1) ;2nd half is all ignored ; to64 db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef' db 'ghijklmnopqrstuvwxyz0123456789+/' ; rderr db '?Read error',cr,lf,0 wrerr db '?Write error',cr,lf,0 fmterr db '?File format error',cr,lf,0 banner db 'Base64 to binary translator by John Wilson ' ; ibuf db ibufl dup(?) obuf db obufl dup(?) ; code ends end start