LC-3 Encryption Program

30 November -0001

This LC-3 program performs simple encryption and decryption of character strings. The encryption algorithm consists of a numeric key from 1 to 9. This key is used to encrypt or decrypt the input string by toggling the low order bit of each character and then adding the key to encrypt and subtracting the key to decrypt each character (depending on the specification of the input). This program was written as part of a class assignment and is assumed to work on character strings of 10 characters or fewer.

My main motivation for posting this code is the dearth of LC-3 code samples available online. LC-3 (or Little Computer 3) is an architecture used for instructional purposes only.

	;Name: Justin Klein Keane
	;Email: justin@madirish.net
	;Date Last Modified: Oct 18, 2007

	;Encryption Program


	.ORIG x3000		;start of program

	;FILL IN YOUR CODE BELOW
	LEA R0, P1
	PUTS	;output the instructions
	
IN1	AND R3,R3,#0	;clear R3
	IN		;Get the input
	ADD R3,R0,#0	;put the input in R3 for holding
	LD R6, CHARE 	;Use R6 to hold -E
	NOT R6,R6
	ADD R6, R6, #1
	ADD R2, R3, R6	;Use R2 to test value of R3 (input)
	BRz CONT
	LD R6, CHARD	;Use R6 to hold -D
	NOT R6,R6
	ADD R6, R6, #1
	ADD R2, R3, R6	;Use R2 to test value of R3 (input)
	BRz CONT
	BRnp WARN1
	
	CHARD:	.FILL x0044	;value of E
	CHARE:	.FILL x0045	;value of D
	s4100	.FILL x4100
	HEX29:	.FILL x0029
	HEX3A:	.FILL x003A
	HEX30:	.FILL x0030
	
CONT	
	LD R4, s4100	;use R4 to store our target location
	STR R3, R4, #0	;put R3's contents at x4100

IN2	
	AND R1,R1,#0	;clear R1
	AND R2,R2,#0	;clear R2
	AND R3,R3,#0	;clear R3
	AND R4,R4,#0	;clear R4
	LEA R0,P2
	PUTS
	IN		;Get the input
	ADD R3,R0,#0	;put the input in R3 for holding
	;We will check the input by subtracting 30 (hex) and making sure 
	;the result is positive or zero.  Next we will subtract 3A and
	;make sure the result is negative.  If both conditions 
	;are true the vaule must be between 30 and 39 (ASCII 0-9)
	LD R1, HEX30	;Use R1 to hold -30 hex
	NOT R1, R1
	ADD R1, R1, #1
	ADD R2, R3, R1	;Use R2 to test value of R3 (input)
	BRn WARN2
	LD R1, HEX3A	;Use R1 to hold -3A
	NOT R1,R1
	ADD R1, R1, #1
	ADD R2, R3, R1	;Use R2 to test value of R3 (input)
	BRzp WARN2 
			;before storing we'll turn this into a real number, not the ASCII value
	AND R1 R1, #0
	LD R1, HEX30
	NOT R1, R1
	ADD R1, R1, #1
	ADD R4, R4, R0
STORE	LD R4, s4101	;store the value at x4101
	ADD R3, R3, R1	;get the corrected value (for the right hex as opposed to ASCII)
	STR R3, R4, #0
	
CONT2	;Continue right along
	LEA R0, P3
	PUTS		;ask the user for a string
	AND R1,R1,#0	;clear R1
	AND R2,R2,#0	;clear R2
	AND R3,R3,#0	;clear R3
	AND R4,R4,#0	;clear R4
	AND R5,R5,#0	;clear R5 for use as a counter
	ADD R2, R2, x000A	;use R2 as the test value
	NOT R2, R2		;make R2 negative (so we can add and test for 0)
	ADD R2, R2, #1
	
	LD R4, s4102	;store the value starting at x4102
	
LOOPIN	AND R3,R3,#0	;clear R3
	IN
	ADD R3, R0, #0	;put the character in R3
STCHR	
	STR R3, R4, #0
	ADD R4, R4, #1	;increment the counter
	ADD R3, R3, R2
	BRnp LOOPIN	;if this is zero we're done inputting
	
	;now it's time to do the encryption
	;start with the first item in the string,
	;encrypt it and output it to the screen
	
	NOT R4,R4
	ADD R4, R4, #1	;make R4 negative E/D for counter testing
	AND R3,R3,#0	;clear R3 - to use for the encryption key
	LD R3, s4101

	AND R5,R5,#0	;clear R5 for use as a counter
	LD R5, s4102	;load the start into R5
	LD R3, s410B	;load the start of storage for output in R7
	
	;LEA R0, P4
	;PUTS	;output the instructions
	
LOOPOUT	
	ADD R3, R3, #1	;increment storage location (starts with x410C)
	AND R2,R2,#0	;clear R2 (use to test EOL)
	ADD R2, R2, x000A	;use R2 as the test value
	NOT R2, R2		;make R2 negative (so we can add and test for 0)
	ADD R2, R2, #1
	
	AND R4, R4, #0	;clear R4 for test output
	AND R1,R1,#0	;clear R1 (used to hold the character in question)
	AND R6,R6,#0	;clear R6 for misc use
	
	LDR R1, R5, #0	;load the character we're working on into R1
	ADD R5, R5, #1  ;increment the counter
	ADD R4, R1, R2	;check to see if this character is the newline
	BRz GOODBYE
	
GETOP	AND R2, R2, #0	;clear R2 to test for Encryption/Decryption
	LD R2, s4100	;load the value of x4100 into R2 (LD then LDR) test if we're encrypting or decrypting
	LDR R2, R2, #0
	LD R6, CHARNE
	ADD R2, R2, R6
	BRz ENCHAR
	
	LD R2, s4100
	LDR R2, R2, #0
	LD R6, CHARND
	ADD R2, R2, R6
	BRz DECHAR

	CHARNE:	.FILL xFFBB	;this is -E
	CHARND:	.FILL xFFBC	;this is -D
	s410B:	.FILL x410B	;this is the start of the storage location
	
ENCHAR	;encrypt the character in R1
	;the first step is to toggle the least significant bit (add one if the char is even, minus one if it's odd)
	ADD R2, R1, #0	;load the character in question into R2
	AND R6, R6, #0	;clear R6
	ADD R6, R6, 2	;load -2 into R6 (we use this to test for even or odd)
	NOT R6, R6
	ADD R6, R6, #1
	
EVNODD	
	ADD R2, R2, R6	;decrement R2 by 2, looking for a result of 0 or -1
	BRz ENCEVN	;R2 is even
	BRn ENCODD	;R2 is odd
	BRp EVNODD	;loop again
			
ENCEVN	;it's even, we have to add one
	ADD R1, R1, x0001
	BRnzp ENC

ENCODD	;it's odd, we have to sub one
	AND R0, R0, #0	;load R0 with -1
	ADD R0, R0, #1
	NOT R0, R0
	ADD R0, R0, #1
	ADD R1, R1, R0
	
ENC	;now we'll do the rest of the encryption
	LD R0, s4101	;load the encryption key into R0 (from x401)
	LDR R0, R0, #0
	ADD R0, R1, R0	;add the encryption key
	STR R0, R3, #0	;store the character
	;OUT		;output the character
	BRnzp LOOPOUT	;get the next character
	
	

DECHAR	;decrypt the character (first subtract the key then do even odd test to flip least significant bit)
	LD R0, s4101	;load the encryption key into R0 (from x401)
	LDR R0, R0, #0
	NOT R0, R0
	ADD R0, R0, #1
	ADD R0, R0, R1	;load the character into R0, we'll manipulate it there
	
	ADD R2, R0, #0	;clear R2, for use testing even/odd of the char
	AND R6, R6, #0	;clear R6
	ADD R6, R6, 2	;load -2 into R6 (we use this to test for even or odd)
	NOT R6, R6
	ADD R6, R6, #1
	
DEVNODD	
	ADD R2, R2, R6	;decrement R2 by 2, looking for a result of 0 or -1
	BRz DECEVN	;R2 is even
	BRn DECODD	;R2 is odd
	BRp DEVNODD	;loop again
			
DECEVN	;it's even, we have to add one
	ADD R0, R0, x0001
	BRnzp DENC

DECODD	;it's odd, we have to sub one
	AND R1, R1, #0	;load R1 with -1
	ADD R1, R1, #1
	NOT R1, R1
	ADD R1, R1, #1
	ADD R0, R1, R0
	
DENC	
	STR R0, R3, #0	;store the character
	;OUT		;output the character
	BRnzp LOOPOUT	;get the next character	
	
GOODBYE	
	LEA R0, P4
	PUTS	;output the final message
	LD R1, s410B
FINLOOP	
	ADD R1, R1, #1	;increment the output (start with x410C)
	LDR R0, R1, #0	;load the next character into R0
	ADD R0, R0, #0	;check to see if we're done
	BRz ENDER
	OUT
	BRnzp FINLOOP
	
ENDER
	LEA R0, GB	;close out nicely
	PUTS
HALT

WARN1	LEA R0, ILLEGAL
	PUTS
	BRnzp IN1
WARN2		
	LEA R0, ILLEGAL
	PUTS
	BRnzp IN2


s4101:	.FILL x4101
s4102:	.FILL x4102

P1:	.STRINGZ "Type E to Encrypt or D to Decrypt:  \n"
P2:	.STRINGZ "\nEnter Encryption Key value between 1 and 9:\n"
P3:	.STRINGZ "\nInput a msg <= 10 chars, then press enter :\n"
P4:	.STRINGZ "\nEncrypted/Decrypted msg is:\n"
GB:	.STRINGZ "\n"
ILLEGAL:	.STRINGZ "\nIllegal Input, Try Again!\n"
KEY:	.FILL x4101
NEG1:	.FILL xFEEE
NEG2:	.FILL xFFFE	;this is -2
Newline:	.STRINGZ "\n";
.END