;Alto->8086 small-c compiler rev 2.0
C←CODE SEGMENT

$INCLUDE(8086LIB.D)

$INCLUDE(DESSofter.DEC)

ASSUME CS:C←CODE, DS:C←DATA

; #include <Env.h>

; extern Block();

; extern Encrypt();

; extern MoveBlock();

; extern DoubleDifference();

; char parityTable[16];

; struct Words4 { int words[4]; };

; EncryptBlock(key, from, to) int *key; struct Words4 *from, *to; {
←EncryptBlock:
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	CryptData(key, 1, from, to, dirEncrypt, slECB, 0); };

;	BX ← ←key
MOV BX,[BP+4]
PUSH BX
MOV BX,1
PUSH BX

;	BX ← ←from
MOV BX,[BP-2]
PUSH BX

;	BX ← ←to
MOV BX,[BP-4]
PUSH BX
MOV BX,1
PUSH BX
XOR BX,BX
MOV CX,0200X
CALL ←CryptData
ADD SP,0AX
MOV SP,BP
POP BP
RET;

; DecryptBlock(key, from, to) int *key; struct Words4 *from, *to; {
←DecryptBlock:
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	CryptData(key, 1, from, to, dirDecrypt, slECB, 0); };

;	BX ← ←key
MOV BX,[BP+4]
PUSH BX
MOV BX,1
PUSH BX

;	BX ← ←from
MOV BX,[BP-2]
PUSH BX

;	BX ← ←to
MOV BX,[BP-4]
PUSH BX
XOR BX,BX
PUSH BX
XOR BX,BX
MOV CX,0200X
CALL ←CryptData
ADD SP,0AX
MOV SP,BP
POP BP
RET;

; CBCCheckDecrypt(key, nBlks, from, to, seed) int *key, nBlks;
←CBCCheckDecrypt:

; 		struct Words4 *from, *to, *seed; {
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	CryptData(key, nBlks, from, to, dirDecrypt, slCBCCheck, seed); };

;	BX ← ←key
MOV BX,[BP+8]
PUSH BX

;	BX ← ←nBlks
MOV BX,[BP+6]
PUSH BX

;	BX ← ←from
MOV BX,[BP+4]
PUSH BX

;	BX ← ←to
MOV BX,[BP-2]
PUSH BX
XOR BX,BX
PUSH BX

;	BX ← ←seed
MOV BX,[BP-4]
MOV CX,0400X
CALL ←CryptData
ADD SP,0AX
MOV SP,BP
POP BP
RET;

; XOR64(a,b,out) int a[], b[], out[]; {
←XOR64:
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	int i;

; 	for (i=0; i<4; ++i) out[i] = a[i] ↑ b[i]; };
PUSH DX
MOV WORD PTR [BP-6],0
X3:

;	BX ← ←i
POP BX
PUSH BX
CMP BX,4
JGE X2
JR X1
X4:
INC WORD PTR [BP-6]
JR X3
X1:

;	BX ← ←i
POP BX
PUSH BX

;	CX ← ←out
MOV CX,[BP-4]
SAL BX
ADD BX,CX

;	CX ← ←i
POP CX
PUSH CX

;	AX ← ←a
MOV AX,[BP+4]
SAL CX
ADD CX,AX
MOV DI,CX
MOV CX,[DI]

;	AX ← ←i
POP AX
PUSH AX
PUSH CX

;	CX ← ←b
MOV CX,[BP-2]
SAL AX
ADD AX,CX
MOV DI,AX
MOV CX,[DI]
POP AX
XOR AX,CX
MOV [BX],AX
JR X4
X2:
MOV SP,BP
POP BP
RET;

; OKToContinue(flag) int *flag; { *flag = true; };
←OKToContinue:
PUSH BP
MOV BP,SP
PUSH BX

;	BX ← ←flag
POP BX
PUSH BX
MOV WORD PTR [BX],0FFFFX
MOV SP,BP
POP BP
RET;

; CryptData(keyP, nBlks, from, to, direction, mode, firstSeed)
←CryptData:

; 	int *keyP;

; 	int nBlks;

; 	struct Words4  from[], to[];

; 	int direction, mode;

; 	struct Words4 *firstSeed; {
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	struct ECB ecb;

; 	struct Words4 newSeed;

; 	struct Words4 seed;

; 	struct Words4 *seedP;

; 	int okToContinue, blk;
ADD SP,0FFDAX

; 	seedP = &seed;
;&←seed
LEA BX,[BP-36]

;	←seedP ← BX
MOV [BP-38],BX

; 	MoveBlock(seedP, firstSeed, 4);

;	BX ← ←seedP
MOV BX,[BP-38]
PUSH BX
MOV BX,4

;	CX ← ←firstSeed
MOV CX,[BP-4]
CALL ←MoveBlock
POP DX

; 	if (to==0) to = from;

;	BX ← ←to
MOV BX,[BP+6]
OR BX,BX
JNZ X5

;	BX ← ←from
MOV BX,[BP+8]

;	←to ← BX
MOV [BP+6],BX
X5:

; 	ecb.kp = keyP;

;	BX ← ←keyP
MOV BX,[BP+12]

;	←ecb+2 ← BX
MOV [BP-18],BX

; 	ecb.encrypt = direction;

;	BX ← ←direction
MOV BX,[BP+4]

;	←ecb+0AX ← BX
MOV [BP-10],BX

; 	ecb.item = (int) &okToContinue;
;&←okToContinue
LEA BX,[BP-40]

;	←ecb+0CX ← BX
MOV [BP-8],BX

; 	ecb.proc = (int) &OKToContinue;
MOV BX,OFFSET ←OKToContinue

;	←ecb+0EX ← BX
MOV [BP-6],BX

; 	if (mode == slCBCCheck && direction == dirEncrypt && nBlks > 0) {

;	BX ← ←mode
MOV BX,[BP-2]
CMP BX,0400X
JNZ X7

;	BX ← ←direction
MOV BX,[BP+4]
CMP BX,1
JNZ X8

;	BX ← ←nBlks
MOV BX,[BP+10]
CMP BX,0
JLE X8
MOV AL,1
JR X9
X8:
XOR AL,AL
X9:
OR AL,AL
JZ X7
MOV AL,1
JR X10
X7:
XOR AL,AL
X10:
OR AL,AL
JZ X6

; 		for (blk=0; blk<nBlks-1; ++blk)
MOV WORD PTR [BP-42],0
X13:

;	BX ← ←nBlks
MOV BX,[BP+10]
DEC BX

;	CX ← ←blk
POP CX
PUSH CX
CMP CX,BX
JGE X12
JR X11
X14:
INC WORD PTR [BP-42]
JR X13
X11:

; 			XOR64(&from[nBlks-1], &from[blk], &from[nBlks-1]);

;	BX ← ←nBlks
MOV BX,[BP+10]
DEC BX

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX
PUSH BX

;	BX ← ←blk
MOV BX,[BP-42]

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	CX ← ←nBlks
MOV CX,[BP+10]
DEC CX

;	AX ← ←from
MOV AX,[BP+8]
SAL CX
SAL CX
SAL CX
ADD CX,AX
XCHG BX,CX
CALL ←XOR64
POP DX
JR X14
X12:

; 		Block(); };
CALL ←Block
X6:

; 	if (mode == slECB) {

;	BX ← ←mode
MOV BX,[BP-2]
CMP BX,0200X
JNZ X15

; 		ecb.count = nBlks*8; /* Why beat around the bush? */

;	BX ← ←nBlks
MOV BX,[BP+10]
SAL BX
SAL BX
SAL BX

;	←ecb+8 ← BX
MOV [BP-12],BX

; 		ecb.srcp = from;

;	BX ← ←from
MOV BX,[BP+8]

;	←ecb+4 ← BX
MOV [BP-16],BX

; 		ecb.dstp = to;

;	BX ← ←to
MOV BX,[BP+6]

;	←ecb+6 ← BX
MOV [BP-14],BX

; 		Docrypt(&ecb); return; };
;&←ecb
LEA BX,[BP-20]
CALL ←Docrypt
MOV SP,BP
POP BP
RET;
X15:

; 	ecb.count = 8;
MOV WORD PTR [BP-12],8

; 	for (blk=0; blk<nBlks; ++blk) {
MOV WORD PTR [BP-42],0
X18:

;	BX ← ←nBlks
MOV BX,[BP+10]

;	CX ← ←blk
POP CX
PUSH CX
CMP CX,BX
JGE X17
JR X16
X19:
INC WORD PTR [BP-42]
JR X18
X16:

; 		if (direction==dirEncrypt) XOR64(&from[blk], seedP, &from[blk]);

;	BX ← ←direction
MOV BX,[BP+4]
CMP BX,1
JNZ X20

;	BX ← ←blk
POP BX
PUSH BX

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX
PUSH BX

;	BX ← ←blk
MOV BX,[BP-42]

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	CX ← ←seedP
MOV CX,[BP-38]
CALL ←XOR64
POP DX

; 		else MoveBlock(&newSeed, &from[blk], 4);
JR X21
X20:
;&←newSeed
LEA BX,[BP-28]
PUSH BX

;	BX ← ←blk
MOV BX,[BP-42]

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX
PUSH BX
MOV BX,4
POP CX
CALL ←MoveBlock
POP DX
X21:

; 		ecb.srcp = &from[blk];

;	BX ← ←blk
POP BX
PUSH BX

;	CX ← ←from
MOV CX,[BP+8]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	←ecb+4 ← BX
MOV [BP-16],BX

; 		ecb.dstp = &to[blk];

;	BX ← ←blk
POP BX
PUSH BX

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	←ecb+6 ← BX
MOV [BP-14],BX

; 		Docrypt(&ecb);
;&←ecb
LEA BX,[BP-20]
CALL ←Docrypt

; 		if (direction == dirEncrypt) seedP = &to[blk];

;	BX ← ←direction
JR $+5
X17:
JMP X23
MOV BX,[BP+4]
CMP BX,1
JNZ X22

;	BX ← ←blk
POP BX
PUSH BX

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	←seedP ← BX
MOV [BP-38],BX

; 		else {XOR64(&to[blk], seedP, &to[blk]); MoveBlock(seedP, &newSeed, 4); }; };
JR X24
X22:

;	BX ← ←blk
POP BX
PUSH BX

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX
PUSH BX

;	BX ← ←blk
MOV BX,[BP-42]

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	CX ← ←seedP
MOV CX,[BP-38]
CALL ←XOR64
POP DX

;	BX ← ←seedP
MOV BX,[BP-38]
PUSH BX
MOV BX,4
;&←newSeed
LEA CX,[BP-28]
CALL ←MoveBlock
POP DX
X24:
JMP X19
X23:

; 	Block();
CALL ←Block

; 	if (mode == slCBCCheck && direction == dirDecrypt && nBlks > 0) {

;	BX ← ←mode
MOV BX,[BP-2]
CMP BX,0400X
JNZ X26

;	BX ← ←direction
MOV BX,[BP+4]
OR BX,BX
JNZ X27

;	BX ← ←nBlks
MOV BX,[BP+10]
CMP BX,0
JLE X27
MOV AL,1
JR X28
X27:
XOR AL,AL
X28:
OR AL,AL
JZ X26
MOV AL,1
JR X29
X26:
XOR AL,AL
X29:
OR AL,AL
JZ X25

; 		for (blk=0; blk<nBlks-1; ++blk)
MOV WORD PTR [BP-42],0
X32:

;	BX ← ←nBlks
MOV BX,[BP+10]
DEC BX

;	CX ← ←blk
POP CX
PUSH CX
CMP CX,BX
JGE X31
JR X30
X33:
INC WORD PTR [BP-42]
JR X32
X30:

; 			XOR64(&to[nBlks-1], &to[blk], &to[nBlks-1]);

;	BX ← ←nBlks
MOV BX,[BP+10]
DEC BX

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX
PUSH BX

;	BX ← ←blk
MOV BX,[BP-42]

;	CX ← ←to
MOV CX,[BP+6]
SAL BX
SAL BX
SAL BX
ADD BX,CX

;	CX ← ←nBlks
MOV CX,[BP+10]
DEC CX

;	AX ← ←to
MOV AX,[BP+6]
SAL CX
SAL CX
SAL CX
ADD CX,AX
XCHG BX,CX
CALL ←XOR64
POP DX
JR X33
X31:

; 		Block(); }; }; /* CryptData */
CALL ←Block
X25:
MOV SP,BP
POP BP
RET;

; Docrypt(ecb) struct ECB *ecb; {
←Docrypt:
PUSH BP
MOV BP,SP
PUSH BX

; 	int *okToContinue;

; 	int i;

; 	char *from, *to, *key;
ADD SP,0FFF6X

; 	okToContinue = (int *) ecb->item;

;	BX ← ←ecb
MOV BX,[BP-2]
MOV CX,[BX+12]

;	←okToContinue ← CX
MOV [BP-4],CX

; 	*okToContinue = false;

;	BX ← ←okToContinue
MOV BX,[BP-4]
MOV WORD PTR [BX],0

; 	{

; 		from = ecb->srcp;

;	BX ← ←ecb
MOV BX,[BP-2]
MOV CX,[BX+4]

;	←from ← CX
MOV [BP-8],CX

; 		to = ecb->dstp;

;	BX ← ←ecb
MOV BX,[BP-2]
MOV CX,[BX+6]

;	←to ← CX
MOV [BP-10],CX

; 		key = ecb->kp;

;	BX ← ←ecb
MOV BX,[BP-2]
MOV CX,[BX+2]

;	←key ← CX
POP DX
PUSH CX

; 		for (i=0; i<ecb->count; ++i) { to[i] = from[i] ↑ key[i&7]; };
MOV WORD PTR [BP-6],0
X36:

;	BX ← ←ecb
MOV BX,[BP-2]
MOV CX,[BX+8]

;	BX ← ←i
MOV BX,[BP-6]
CMP BX,CX
JGE X35
JR X34
X37:
INC WORD PTR [BP-6]
JR X36
X34:

;	BX ← ←i
MOV BX,[BP-6]

;	CX ← ←to
MOV CX,[BP-10]
ADD BX,CX

;	CX ← ←i
MOV CX,[BP-6]

;	AX ← ←from
MOV AX,[BP-8]
ADD CX,AX
MOV DI,CX
MOV AL,[DI]
PUSH BX

;	BX ← ←i
MOV BX,[BP-6]
AND BX,7

;	CX ← ←key
MOV CX,[BP-12]
ADD BX,CX
MOV CL,[BX]
XOR AL,CL
POP BX
MOV [BX],AL
JR X37
X35:

; 		*okToContinue = true;  Block(); };

;	BX ← ←okToContinue
MOV BX,[BP-4]
MOV WORD PTR [BX],0FFFFX
CALL ←Block

; 	while (!(*okToContinue)) Block(); };
X38:

;	DI ← ←okToContinue
MOV DI,[BP-4]
MOV BX,[DI]
OR BX,BX
JNZ X39
CALL ←Block
JR X38
X39:
MOV SP,BP
POP BP
RET;

; MakeKey(source, key) struct ShortSTRING *source; char key[]; {
←MakeKey:
PUSH BP
MOV BP,SP
PUSH CX
PUSH BX

; 	int i;

; 	int j; char c;
ADD SP,0FFFAX

; 	Zero(key, 4);
MOV BX,4

;	CX ← ←key
MOV CX,[BP-4]
CALL ←Zero

; 	for (i=0; i<source->length; ++i) {
MOV WORD PTR [BP-6],0
X42:

;	DI ← ←source
MOV DI,[BP-2]
MOV BX,[DI]

;	CX ← ←i
MOV CX,[BP-6]
CMP CX,BX
JGE X41
JR X40
X43:
INC WORD PTR [BP-6]
JR X42
X40:

; 		j = i&7;

;	BX ← ←i
MOV BX,[BP-6]
AND BX,7

;	←j ← BX
MOV [BP-8],BX

; 		c=source->text[i];

;	BX ← ←source
MOV BX,[BP-2]
ADD BX,4

;	CX ← ←i
MOV CX,[BP-6]
ADD BX,CX
MOV AL,[BX]

;	←c ← AL
POP DX
PUSH AX

; 		if ('A' <= c && c <= 'Z') c += ('a' - 'A');

;	AL ← ←c
POP AX
PUSH AX
MOV CL,041X
CMP CL,AL
JG X45

;	AL ← ←c
POP AX
PUSH AX
CMP AL,05AX
X45:
JG X44
ADD BYTE PTR [BP-10],020X
X44:

; 		key[j] ↑= c<<1; };

;	BX ← ←j
MOV BX,[BP-8]

;	CX ← ←key
MOV CX,[BP-4]
ADD BX,CX

;	AL ← ←c
POP AX
PUSH AX
SAL AL
XOR [BX],AL
JR X43
X41:

; 	CorrectParity(key); };

;	BX ← ←key
MOV BX,[BP-4]
CALL ←CorrectParity
MOV SP,BP
POP BP
RET;

; CorrectParity(keyP) char keyP[]; {
←CorrectParity:
PUSH BP
MOV BP,SP
PUSH BX

; 	int i;

; 	char c;

; 	int pWord, pBitNo;

; 	if (parityTable[0] != 0x96) InitParityTable();
ADD SP,0FFF8X
MOV AX,WORD PTR ←parityTable
CMP AL,096X
JZ X46
CALL ←InitParityTable
X46:

; 	for (i=0; i<8; ++i) {
MOV WORD PTR [BP-4],0
X49:

;	BX ← ←i
MOV BX,[BP-4]
CMP BX,8
JGE X48
JR X47
X50:
INC WORD PTR [BP-4]
JR X49
X47:

; 		c=keyP[i];

;	BX ← ←i
MOV BX,[BP-4]

;	CX ← ←keyP
MOV CX,[BP-2]
ADD BX,CX
MOV AL,[BX]

;	←c ← AL
MOV [BP-6],AL

; 		pWord = parityTable[c>>4];
MOV CL,4

;	AL ← ←c
MOV AL,[BP-6]
SHR AL,CL
XOR AH,AH
LEA BX,←parityTable
ADD BX,AX
MOV AL,[BX]
XOR AH,AH

;	←pWord ← AX
MOV [BP-8],AX

; 		c=c>>1;

;	AL ← ←c
MOV AL,[BP-6]
SHR AL

;	←c ← AL
MOV [BP-6],AL

; 		pBitNo = 7-(c&7);

;	AL ← ←c
MOV AL,[BP-6]
AND AL,7
MOV CL,7
SUB CL,AL
XOR CH,CH

;	←pBitNo ← CX
POP DX
PUSH CX

; 		pWord = (pWord>>pBitNo)&1;

;	CX ← ←pBitNo
POP CX
PUSH CX

;	BX ← ←pWord
MOV BX,[BP-8]
SHR BX,CX
AND BX,1

;	←pWord ← BX
MOV [BP-8],BX

; 		keyP[i] = (c<<1) | pWord; }; };

;	BX ← ←i
MOV BX,[BP-4]

;	CX ← ←keyP
MOV CX,[BP-2]
ADD BX,CX

;	AL ← ←c
MOV AL,[BP-6]
SAL AL
XOR AH,AH

;	CX ← ←pWord
MOV CX,[BP-8]
OR AX,CX
MOV [BX],AL
JR X50
X48:
MOV SP,BP
POP BP
RET;

; int DESBlocks(n) int n; { return (n+3)/4; };
←DESBlocks:
PUSH BP
MOV BP,SP
PUSH BX

;	BX ← ←n
POP BX
PUSH BX
ADD BX,3
SAR BX
SAR BX
MOV SP,BP
POP BP
RET;

; struct Words4 randomSeed;

; GetRandomIV(iv) struct Words4 *iv; {
←GetRandomIV:
PUSH BP
MOV BP,SP
PUSH BX

; 	struct Words4 prevSeed, temp;
ADD SP,0FFF0X

; 	MoveBlock(&prevSeed, &randomSeed, 4);
;&←prevSeed
LEA BX,[BP-10]
PUSH BX
MOV BX,4
LEA CX,←randomSeed
CALL ←MoveBlock
POP DX

; 	Timer(&temp);
;&←temp
LEA BX,[BP-18]
CALL ←Timer

;      ReadCalendar(&temp.words[2]);
;&←temp
LEA BX,[BP-14]
CALL ←ReadCalendar

; 	DoubleDifference(&randomSeed, &temp);
;&←temp
LEA BX,[BP-18]
LEA CX,←randomSeed
CALL ←DoubleDifference

; 	Zero(&temp, 4);
MOV BX,4
;&←temp
LEA CX,[BP-18]
CALL ←Zero

; 	CorrectParity(&randomSeed);
LEA BX,←randomSeed
CALL ←CorrectParity

; 	EncryptBlock(&randomSeed, &temp, &randomSeed);
LEA BX,←randomSeed
PUSH BX
LEA BX,←randomSeed
;&←temp
LEA CX,[BP-18]
CALL ←EncryptBlock
POP DX

; 	CorrectParity(&randomSeed);
LEA BX,←randomSeed
CALL ←CorrectParity

; 	EncryptBlock(&randomSeed, &prevSeed, iv); };
LEA BX,←randomSeed
PUSH BX

;	BX ← ←iv
MOV BX,[BP-2]
;&←prevSeed
LEA CX,[BP-10]
CALL ←EncryptBlock
POP DX
MOV SP,BP
POP BP
RET;

; InitParityTable() {
←InitParityTable:
PUSH BP
MOV BP,SP

; 	parityTable[0] = 0x96;
MOV ←parityTable,096X

; 	parityTable[1] = 0x69;
MOV ←parityTable+1,069X

; 	parityTable[2] = 0x69;
MOV ←parityTable+2,069X

; 	parityTable[3] = 0x96;
MOV ←parityTable+3,096X

; 	parityTable[4] = 0x69;
MOV ←parityTable+4,069X

; 	parityTable[5] = 0x96;
MOV ←parityTable+5,096X

; 	parityTable[6] = 0x96;
MOV ←parityTable+6,096X

; 	parityTable[7] = 0x69;
MOV ←parityTable+7,069X

; 	parityTable[8] = 0x69;
MOV ←parityTable+8,069X

; 	parityTable[9] = 0x96;
MOV ←parityTable+9,096X

; 	parityTable[10] = 0x96;
MOV ←parityTable+0AX,096X

; 	parityTable[11] = 0x69;
MOV ←parityTable+0BX,069X

; 	parityTable[12] = 0x96;
MOV ←parityTable+0CX,096X

; 	parityTable[13] = 0x69;
MOV ←parityTable+0DX,069X

; 	parityTable[14] = 0x69;
MOV ←parityTable+0EX,069X

; 	parityTable[15] = 0x96; };
MOV ←parityTable+0FX,096X
MOV SP,BP
POP BP
RET;

; Externals Declared Here
PUBLIC ←parityTable
PUBLIC ←EncryptBlock
PUBLIC ←CryptData
PUBLIC ←DecryptBlock
PUBLIC ←CBCCheckDecrypt
PUBLIC ←XOR64
PUBLIC ←OKToContinue
PUBLIC ←Docrypt
PUBLIC ←MakeKey
PUBLIC ←CorrectParity
PUBLIC ←InitParityTable
PUBLIC ←DESBlocks
PUBLIC ←randomSeed
PUBLIC ←GetRandomIV

C←CODE ENDS

; Number of Bytes of Code = 055DX, (1373)