;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* This is a demonstration program that shows how to encrypt *;
;* a file with a password using the XOR operator. *;
;* Compiled by TASM 3.1 for 8086 CPU under DOS (small memory). *;
;* *;
;* Written by Zsolt Nagy Perge in October 2000, Pensacola, FL. *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
CODE SEGMENT
ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE
ORG 00100h
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* INITIALIZATION *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
ENTRY:
; PSP PARAMETER STRING ANALYZATION
XOR BL,BL ; tells if we are reading letters or spaces
XOR CL,CL ; counts the number of parameter strings
MOV DI,OFFSET ParamPtr ; points to the parameter ptr table
MOV SI,00081h ; points to the parameter string
CLD
GetParam:
; Read one character from the parameter string.
LODSB
; Identify it...
CMP AL,00Dh ; END OF PARAMETER?
JE GetParam_Exit
CMP AL,020h ; SPACE?
JE GetParam_Space
CMP AL,009h ; TAB?
JE GetParam_Space
; If AL was not a space, neither a TAB character,
; then it must be the character of a parameter.
; Did we previously save this parameter?
; If yes, then continue the loop.
OR BL,BL
JNE GetParam
; If no, then we'll save its address in the parameter ptr table now.
MOV AX,SI
DEC AX
STOSW
; Increment the parameter counter,
; and then set the flag because we have saved this parameter.
INC CL
GetParam_SetState:
; We change the flag now.
; This helps us remember what we just did before this loop...
NOT BL
JMP GetParam
GetParam_Space:
; Have we just read a parameter?
; Let's check the flag if it is zero.
; If no, then continue the loop.
OR BL,BL
JE GetParam
; If yes, then we must put a NULL character at its end,
; and then clear the flag because we are done with this parameter.
MOV BYTE PTR [SI-01],00
JMP GetParam_SetState
GetParam_Exit:
; Finally, we are finished,
; but we still have to put one NULL character
; at the end of the parameter string to close it.
MOV BYTE PTR [SI-01],00
; Now, CL contains the number of parameter strings given,
; and ParamPtr contains the pointers to each parameter string.
; PARAMETER CHECKING
; Here, we want to make sure that we got all the needed parameters.
; Only two parameters are required.
; If we got less, then we jump to Error and display Usage.
CMP CL,002h
MOV DX,OFFSET Usage
JB Error
; Assume that the password was given as a parameter.
MOV AX,[ParamPtr[4]]
MOV [PWP],AX
; Make sure that we have the password...
JA HavePassword
; Unfortunately the user forgot to give us the password,
; but we will remind him now.
MOV AH,009h
MOV DX,OFFSET AskPassword
INT 021h
; Ask the user to enter the password.
MOV AH,00Ah
MOV DX,OFFSET Buffer
INT 021h
MOV AH,009h
MOV DX,OFFSET CRLF
INT 021h
; Put a NULL character at the end of the password string.
MOV AL,[Buffer[1]]
CBW
MOV SI,AX
ADD SI,OFFSET Password
MOV [SI],AH
; Store the password pointer at PWP.
; Originally PWP was pointing to the thrid parameter in ParamPtr.
MOV [PWP],OFFSET Password
HavePassword:
; Equal PWC to PWP.
MOV AX,[PWP]
MOV [PWC],AX
; Now that we have the password,
; we may go ahead and open the files.
; Open input file for read-only access...
MOV AX,03D00h
MOV DX,[ParamPtr[0]]
INT 021h
MOV [InFile],AX
MOV DX,OFFSET InFileErr
JC Error
; Create normal output file...
MOV AH,03Ch
MOV CX,00000h
MOV DX,[ParamPtr[2]]
INT 021h
MOV [OutFile],AX
MOV DX,OFFSET OutFileErr
JC Error
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* MAIN LOOP *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
MainLoop:
; Fill the buffer when necessary.
; This function will never return when we reach the end of file.
CALL Read
; Load password character and do the encryption...
MOV DI,[PWC]
MOV AL,[DI]
; We are not removing the character; we just XOR it in the buffer.
; The write function will be called by the read function before
; it wants to read in a new buffer, therefore the buffer
; will flush itself whenever it is necessary.
XOR [SI],AL
; Increment PWC.
INC [PWC]
; Reset PWC if it points to the end of the password.
MOV SI,[PWC]
LODSB
OR AL,AL
JNE MainLoop
MOV SI,[PWP]
MOV [PWC],SI
JMP MainLoop
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* Displays an error message and terminates the program *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
Error:
; Print a message to stdout.
MOV AH,009h
INT 021h
; Close all files and exit with error code 1.
MOV AX,04C01h
INT 021h
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* Writes each byte from the buffer to the output file *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
WriteBuffer:
; Write resulting byte to the output file.
MOV AH,040h
MOV BX,[OutFile]
MOV CX,SI
MOV DX,OFFSET DATABUFFER
INT 021h
; Check for errors...
CMP AX,[BFULL]
MOV DX,OFFSET WritingErr
JNE Error
RET
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* Reads one byte of data *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
Read:
; If we do not have any leftovers in the data buffer,
; then we'll have to fill it up again.
MOV SI,[BPTR]
CMP SI,[BFULL]
JAE ReadBuffer
; Return the pointer to the new character in SI.
ADD SI,OFFSET DATABUFFER
INC [BPTR]
RET
ReadBuffer:
; We have to flush the buffer before we read.
; Nothing will be written when SI is zero.
; So, we don't have to worry about what's going to happen on the first round.
CALL WriteBuffer
; Now, we'll try to read in a buffer.
MOV AH,03Fh
MOV BX,[InFile]
MOV CX,BUFFERSIZE
MOV DX,OFFSET DATABUFFER
INT 021h
MOV [BFULL],AX
MOV [BPTR],0000
; If were not able to read anything,
; then certainly we've reached the end of file.
OR AX,AX
JNE Read
; Close all files and exit with error code 0.
MOV AX,04C00h
INT 021h
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
;* DATA AREA *;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *;
InFileErr DB "Cannot open input file.", 13, 10, 36
OutFileErr DB "Cannot open output file.", 13, 10, 36
WritingErr DB "Cannot write to output file.", 13, 10, 36
AskPassword DB "Password: $"
; The following two lines must stay in this order!
Usage DB "Usage: XOR