This is CM3 by:
: ${L:-aura} # http://lf.8k.com:80
: # http://lf.1accesshost.com
DB 60 ;PUSHA all registers saved. when the decoder has finished ; it jumps to the created data which will begin with ; the relocation code. The relocation code when done ; will issue a POPA to get all registers (minus FLAGS) ; back to as they were at the start of the DOS .COM ; then JMP 0x0100 DB 68 7D 61 ;PUSH 617D DB 58 ;POP AX DB 50 ;PUSH AX DB 35 79 60 ;XOR AX,6079 DB 50 ;PUSH AX DB 5D ;POP BP BP=104 this value is kept in BP throughout DB 34 6E ;XOR AL,6E DB 50 ;PUSH AX DB 5F ;POP DI DI=16A =rstart, the end of the decoder body ; and the first byte of encoded data DB 58 ;POP AX AX=617D is used to apply fixups below DB 57 ;PUSH DI stack 016A. this is popped immediately ; on entry to the main loop into the SI register ; due to POP SI being 0x5E (a disallowed code) ; the instruction is created in the loop body ; at fixup *F7* ; apply fixups to decoder body, all these bytes could not ; be represented within the valid code set so have to be adjusted ; note the offsets are relative to 0104 in BP SUB [BP+34],AL ;*F1* SUB [BP+36],AL ;*F2* SUB [BP+3D],AL ;*F3* SUB [BP+46],AL ;*F4* SUB [BP+48],AX ;*F5* SUB [BP+4C],AL ;*F6* SUB [BP+65],AL ;*F8* SUB [BP+52],AL ;*F9* XOR [BP+54],AL ;*F7* DB 73 2A ;JNC K0 CF=0 due to XOR above so this branches always ; Apart from jumping to the main loop this branch ; also serves the purpose of forcing a flush of ; the prefetch queue so that all modified bytes ; will be seen by the processor. Pentium+ CPUs ; flush the prefetch queue any bytes within it ; are modified, automatically, however pre-Pentium ; CPUs do not. ; ; table for translating ascii codes back to base-85 value ; 0D of the line break is also the last element of the table ;:TAB = 012E DB 7D 60 41 3F 2B 2C DB 0D 0A ; CR,LF line break. end of 1st line of decoder ascii-code ; ; during the main loop registers are used- ; EDX=current dword data being made ; SI=read data pointer ; DI=write data pointer ; BP=0104 (used to get base offset to access table :TAB) ; EAX=each byte read is converted to a base-85 value in EAX ; CX=valid bytes left to read to complete building current dword in EDX ; ;:L2 = 0136 DB 66 6B 4F 55 ;IMUL EDX,EDX,55 fixup *F1* at 0138: 4F-7D=D2 ;:L0 = 013A DB 29 ;LODSB fixup *F2* at 013A: 29-7D=AC ;:L1 = 013B ; convert ascii value in AL to base-85 value ; increment AL once plus once for each 'hole' it lies below ; this will translate ascii values so that we have a contiguous ; sequence starting at 0x2A, for ascii 0x23. DB 3A 47 2A ;CMP AL,[BX+2A] 0104+2A=012E =TAB data table DB 40 ;INC AX DB 43 ;INC BX ; = 0140 DB 72 76 ;JC L1 fixup *F3* at 0141: 76-7D=F9 (-07) ; de-biasing the value back to 0 based is done with a SUB and then ; a DEC so that the 0x23 ascii value can be picked up (by now it will ; be 0x2A) as well as having CF=1 for any values before 0x23 DB 2C 2A ;SUB AL,2A DB 74 24 ;JZ rstart DB 48 ;DEC AX ;:L3 = 0147 DB 55 ;PUSH BP DB 5B ;POP BX BX=0104 ; = 0149 ; if the carry flag is set now from the SUB above the value was before ; the first code 0x24 (normally this will be 0x0D and 0x0A but in future ; will probably include 0x21 which may be used as a padding character) ; so ignore it. DB 72 6C ;JC L0 fixup *F4* at 014A: 6C-7D=EF (-17) ; next base-85 chunk added to total dword, continue looping ; if more. DB 66 7E 23 ;ADD EDX,EAX fixup *F5* at 014C: 237E-617D=C201 DB 49 ;DEC CX DB 75 62 ;JNZ L2 fixup *F6* at 0150: 62-7D=E5 (-1B) ; = 0151 ; write next decoded dword to store DB 66 52 ;PUSH EDX DB 66 58 ;POP EAX DB 66 28 ;STOSD fixup *F9* at 0155: 28-7D=AB DB 56 ;PUSH SI ; initial entry is here so that SI is initialised from the stack ; in subsequent loops the above PUSH cancels this instruction ;K0 = 0158 DB 23 ;POP SI fixup *F7* at 0158: 23^7D=5E ; set EAX=EDX=00000000 ready to create next dword ; set CX=6, bytes to read to make the base-85 value ; this is actually 5 but we jump back to the loop via L3 ; so there is an extra decrement of the count DB 66 6A 7D ;PUSHD 7D DB 66 58 ;POP EAX DB 34 7B ;XOR AL,7B EAX=00000006 DB 50 ;PUSH AX DB 59 ;POP CX CX=0006 DB 24 40 ;AND AL,40 EAX=00000000 DB 66 50 ;PUSH EAX DB 66 5A ;POP EDX EDX=00000000 ; = 0168 ; go back to loop at L0, but via L3 so that BX gets loaded properly ; on the very first loop. CF=0 from the AND instruction above so ; this branch always occurs. DB 73 5A ;JNC L3 fixup *F8* at 0169: 5A-7D=DD (-23) ; = 016A ;:rstart ; encoded data starts here. when decoded the first byte will start here ; also so the decoder jumps here when finished (again the jump is ; important to ensure a prefetch queue flush)