home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
mskermit.tar.gz
/
mskermit.tar
/
msbpcg.asm
< prev
next >
Wrap
Assembly Source File
|
1990-06-19
|
8KB
|
311 lines
; Written by Dan Norstedt, Stockholm, Sweden Last edit 17-Feb-1990
;
; This program is placed in the public domain.
;
; Use this program to generate MSBPCT.COM for MS-DOS with the commands:
;
; C>MASM MSBPCG;
; C>LINK MSBPCG;
; C>MSBPCG >MSBPCT.COM
;
; The generated MSBPCT.COM file is trick coded, and only contains
; printable 7-bit ASCII characters. Thus, it can be sent as text
; without modifications, just capture it to disk, trim off excess
; text, and execute it. It takes one input argument, the input file.
; If no valid file is given, a Usage: message is given.
;
; The program will decodes about 10Kbyte/sec on my AT hard disk.
;
; The loader and builder portions of this program may be useful for other
; programs, too.
CODE SEGMENT PUBLIC
ASSUME CS:CODE,DS:CODE
ORG 100H
START: JMP GENCOM
ORG 100H+72+1 ; Address where loader starts loading
CODARE:
;----------------------- beginning of MSBPCT code area -----------------------
INBUF EQU ((Offset MSBEND-Offset START+1FFH) AND 0FF00H)
INBSIZ EQU 400H
OUTBUF EQU INBUF+INBSIZ
; CLD ; Already done in the loader
MOV DX,Offset MEMTXT
CMP SP,0FF00H ; Enough memory?
JB OUTMSG
MOV SI,80H ; Point at line length byte
XOR AH,AH
LODSB ; Get it
XCHG AX,BX
MOV Word Ptr [SI+BX],0 ; Clear end of command string
LEA DX,[SI+1]
MOV AX,3D00H ; Try to open the file
INT 21H
MOV DX,Offset USETXT ; Tell usage if we can't open input file
JNC OPENOK
OUTMSG: MOV AX,901H ; Output error text
EXIT: PUSH AX
INT 21H
POP AX ; Set up exit code
MOV AH,4CH
INT 21H
OPENOK: XCHG BX,AX ; Save input handle
MOV DX,Offset FILTXT ; Output header
MOV AH,9
MOV SI,OUTBUF ; Temorary buffer for output filename
RDMORE: INT 21H
MOV AH,3FH ; Read a character
MOV CX,1
MOV DX,SI
INT 21H
ERROR: MOV DX,Offset ERRTXT
JC OUTMSG ; Error if failure here
DEC AX
JNZ OUTMSG
LODSB
XCHG AX,DX
MOV AH,2 ; Prepare for output
CMP DL,20H
JA RDMORE ; Printable character -> save and output
MOV AH,3CH ; Prepare for file create
XOR CX,CX
MOV [SI-1],CL ; Make input filename buffer NUL terminated
MOV DX,OUTBUF ; Pointer to file name
MOV DI,DX
INT 21H ; Create output file
JC ERROR
XCHG AX,BX ; Save file output file handle in BX
XCHG AX,BP ; Input file handle to BP
READBU: PUSH DX ; Save shift count (initial value in DL = 0)
MOV DX,OUTBUF
MOV CX,DI
SUB CX,DX ; Compute size of output buffer
JZ NOWRIT ; Zero, skip write
MOV AH,40H ; Write it out
INT 21H
JC ERROR
SUB AX,CX ; Write failed?
JC ERROR
NOWRIT: MOV DI,DX ; No, reset output buffer pointer
MOV DX,INBUF ; Load input buffer pointer
MOV SI,DX ; Set up for later use
MOV CX,INBSIZ ; Read one buffer of appropriate size
MOV AH,3FH
XCHG BX,BP ; Swap input and output file handles
INT 21H
XCHG BX,BP
JC ERROR
XCHG AX,CX
MOV AX,3E00H ; Load good close function code, just in case
JCXZ EXIT ; End of input file, do the good exit
POP DX ; Regain shift count (in DL)
INLOOP: LODSB ; Get a character
SUB AL,30H
JL CHRDON ; Junk, throw away
MOV AH,DH ; Good one, get old saved char to AH
MOV DH,AL ; Save current instead
CMP AH,4EH ; Old character flags expansion of NULs?
JZ NULLS
SHL AL,1 ; No merge low bits of old char with new char
SHL AL,1
XCHG CX,DX ; Get current shift amount (0, 2, 4 or 6)
SHR AX,CL ; Do shift
XCHG CX,DX
SUB DL,2 ; Adjust for new shift factor,old = 0 -> skip?
JS INLOOR ; Yes, skip
STOSB ; No, save result of shift operation
INLOOR: AND DL,6 ; Adjust shift count if DL was = 0
JMP Short CHRDON ; End loop
NULLS: CBW ; Expand NUL count
CWD ; Reset shift count in DL and NULL flag in DH
PUSH CX ; Save input character left counter
XCHG AX,CX
MOV AL,0
REP STOSB ; Store selected amount of NULs
POP CX ; Restore counter
CHRDON: LOOP INLOOP ; Loop for rest of input block
JMP Short READBU ; Try to read another buffer
USETXT DB 'Usage: MSBPCT file.BOO$'
FILTXT DB 'Unpacking to file: $'
ERRTXT DB 'Error during file I/O$'
MEMTXT DB 'Not enough memory$'
MSBEND:
;-------------------------- end of MSBPCT code area --------------------------
CODEND:
;-- Loader starts here; don't touch unless you REALLY know what's going on --
FIXUP MACRO LABL,OFFS,DAT,DA2,DAS
ORG $+(OFFS)
LABL Label Byte
IFNB <DAS>
IFNB <DA2>
DB (((DAS) OR 65H)-((DAS) AND 65H)) AND 0FFH,0FFH-(DA2)
ORG $-1
ELSE
DB ((DAS)+65H) AND 0FFH
ENDIF
ELSE
DB 0FFH-((DAT) AND 0FFH)
IFNB <DA2>
DB 0FFH-(DA2)
ORG $-1
ENDIF
ENDIF
ORG $-(OFFS)-1
ENDM
FIXBYT MACRO ADDR ; Generate "XOR [BX+ADDR-0FFH],AL" with 8-bit offset
DB 30H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
ENDM
FIXBYH MACRO ADDR ; Generate "XOR [BX+ADDR-0FFH],AH" with 8-bit offset
DB 30H,67H,(Offset ADDR-Offset LOADER+100H)-0FFH
ENDM
FIXWRD MACRO ADDR ; Generate "XOR [BX+ADDR-0FFH],AX" with 8-bit offset
DB 31H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
ENDM
FIXSUB MACRO ADDR ; Generate "SUB [BX+ADDR-0FFH],AL" with 8-bit offset
DB 28H,47H,(Offset ADDR-Offset LOADER+100H)-0FFH
ENDM
LOADER: POP AX
PUSH AX
DEC AX ; Load AX with 0FFFFH
PUSH AX ; Now FF FF 00 00 on stack
INC SP
POP BX ; Load BX with 00FF
FIXBYT XORBXX ; Fix up end of loader code
FIXBYT XORB1
FIXBYT XORB2
FIXWRD XORW1
FIXWRD XORW2
DAA ; Load AL with 65H
FIXSUB SUBB1
FIXSUB SUBB2
JNZ J0JMP ; Break pipeline
J0DST: FIXBYH XORB3
FIXSUB SUBB3
FIXSUB SUBB4
FIXWRD XORX1
; FC
CLD ; Set LODSB direction
FIXUP SUBB1,-1,,,0FCH
; 8D7749 LEA SI,[BX+DATA-0FFH] ; Point at 100H+72
DB 8DH,77H,(Offset DATA-Offset LOADER+100H)-0FFH
FIXUP XORB1,-3,8DH
; 56
PUSH SI ; Copy SI -> DI
; 5F
POP DI
; 46
INC SI
J2DST:
; 2AC2
SUB AL,DL ; Compute real code/data byte
; AA
STOSB ; Save it
FIXUP XORW1,-2,0C2H,0AAH
J1DST:
J3DST:
; AC
LODSB ; Get an encoded data byte
FIXUP XORB2,-1,0ACH
; 40
INC AX
; 3C31
CMP AL,31H ; Printable and >= '0'?
; 7CFA
JL J1DST
J1SRC: FIXUP SUBB2,-1,,,J1DST-J1SRC
; 2C35
SUB AL,'4'+1 ; Yes, '0'-'3' (or '4' = exit code) ?
; 77F3
JA J2DST ; No, store with current prefix code
J2SRC: FIXUP SUBB3,-1,,,J2DST-J2SRC
; B102
MOV CL,2
FIXUP XORB3,-2,0B1H
; D2C8
ROR AL,CL
FIXUP XORX1,-3,,0D2H,2
; 92
XCHG DX,AX ; Yes, just save shifted value
FIXUP XORW2,-2,0C8H,92H
; 75EF
JNZ J3DST ; No, contine loop
J3SRC: FIXUP SUBB4,-1,,,J3DST-J3SRC
; 75D7
J0JMP: JNZ J0DST ; (Dummy branch used to clear prefetch queue)
J0SRC: FIXUP XORBXX,-1,J0DST-J0SRC
DB 34H ; Skip over next byte (34H = XOR AL,nn opcode)
DATA: DB "$" ; CRLF data to make sure JL J1DST taken first time
GENCOM: PUSH CS ; Allow use without EXE2BIN
POP DS
MOV DX,Offset LOADER ; Output LOADER code (!)
MOV AH,9
INT 21H
CLD
MOV SI,Offset CODARE ; Pointer to real MSBPCT code
XOR BP,BP ; Reset columns left counter
MOV BH,17 ; Assure that BH not in range '0'-'3'
BYTLOP: MOV AX,0C01H
SUB AL,[SI] ; Convert MSBPCT code to loader format
INC SI
MOV CL,2
SHL AX,CL ; First byte is top 2 bits of byte+43H
NOT AL
SHR AL,CL ; Second byte is low 6 bits of -byte-3
ADD AL,35H ; Based value is '5' for second byte
CMP AH,BH ; Same prefix as previous byte?
MOV BH,AH
XCHG DX,AX
OUTBYT: XCHG DH,DL ; Swap output order
JZ OUTNHI ; Skip unnecessary prefix byte
DEC BP
JG OUTNCR ; Not 72 chars on the line yet
PUSH DX
MOV DX,Offset CRLF ; 72 chars on line, add CR LF
MOV AH,9
INT 21H
MOV BP,72 ; Restart line pointer
POP DX
OUTNCR: MOV AH,2 ; Output a byte
INT 21H
OUTNHI: XOR DL,DL ; Clear out used code byte
AND DH,DH ; Anything more to print?
JNZ OUTBYT
CMP SI,Offset CODEND ; End of area?
JNZ BYTLOP
MOV DX,Offset ENDTXT ; Yes, add trailer: 34H and CR LF
MOV AH,9
INT 21H
MOV AH,4CH ; End GENCOM program section
INT 21H
ENDTXT DB 34H ; End of file marker for loader
CRLF DB 13,10,"$"
CODE ENDS
END START