.constant
OBJREF 0x40
.end-constant

.main
.var
.end-var
  LDC_W OBJREF
  LDC_W OBJREF
  LDC_W OBJREF
  INVOKEVIRTUAL getnum
  LDC_W OBJREF
  INVOKEVIRTUAL getnum
  INVOKEVIRTUAL min
  INVOKEVIRTUAL print
  HALT
.end-main

.method min(x,y)
.var
.end-var
  ILOAD y
  ILOAD x
  ISUB
  IFLT returny
  ILOAD x
  IRETURN
returny:
  ILOAD y
  IRETURN 
.end-method

.method getnum()
.var
a
.end-var

	BIPUSH 0x0		// initialize a
        ISTORE a
geta:	IN			// read key press
	DUP			// duplicate key for comparison
	BIPUSH 0xa		// if key = cr,
	IF_ICMPEQ return	//   return
	DUP
	BIPUSH 0x30		// if key < "0"
	ISUB			//
	IFLT geta4		//   goto geta4 (key is not a hex digit)
    	DUP
	BIPUSH 0x3a		// else if key < ":"
	ISUB			//
	IFLT geta2		//   goto geta2 (key is numeric character - "0"-"9")
	DUP
	BIPUSH 0x41		// else if key < "A"
	ISUB			//
	IFLT geta4		//   goto geta4 (key is not a hex digit)
	DUP
	BIPUSH 0x46		// else if key > "F"
	SWAP			//  
	ISUB			//
	IFLT geta4		//   goto geta4 (key is not a hex digit)
	DUP			// else (key is letter - "A"-"F")
	OUT			//   print key
	BIPUSH 0x37		//   convert key from character to number
	ISUB			//
	GOTO geta3		//   goto geta3
geta2:  DUP
	OUT			// print key (numeric character)
	BIPUSH 0x30		// convert key from character to number
	ISUB
geta3:  ILOAD a			// shift a left 8 bits
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	DUP
	IADD
	IADD			// add key to a
	ISTORE a
	GOTO geta		// get next key

geta4:	POP			// pop invalid character
	GOTO geta		// get next key

return: OUT			// print cr
	ILOAD a			// load a as return value
	IRETURN			// return
.end-method

.method print( total ) 		// print converts a number into a string of
				//   characters and prints them.  All of the characters
				//   are pushed onto the stack, least significant
				//   digit first, then popped off and printed.
.var
place
index
.end-var

print: 	BIPUSH 0x9		// there are 8 nibbles in each integer--setting
				//   this as nine pushes 10 characters onto the
 				//   stack, thus a total of ten printed digits,
				//   but setting this less does not remove the
				//   two leading zeros, just removes significant
				//   digits
	ISTORE index
	BIPUSH 0x1		// comparison bit
	ISTORE place
print1:	BIPUSH 0x0
	ILOAD index		// index = index - 1
	BIPUSH 0x1
	ISUB
	DUP
	IFEQ pall		// if index = 0  goto pall
	ISTORE index
	ILOAD total		// else
	ILOAD place		//
	IAND			//   if 1st bit of current nibble is zero (total & place)
	IFEQ print2		//     goto print2
	BIPUSH 0x1		//   else set first bit of character
	IADD
print2: ILOAD place		//   place = place << 1 
	DUP
	IADD
	ISTORE place
	ILOAD total
	ILOAD place
	IAND			//   if 2nd bit of current nibble is zero (total & place)
	IFEQ print3		//     goto print3
	BIPUSH 0x2		//   else set second bit of character
	IADD	
print3: ILOAD place		//   place = place << 1
	DUP
	IADD
	ISTORE place
	ILOAD total
	ILOAD place
	IAND			//   if 3rd bit of current nibble is zero (total & place)
	IFEQ print4		//     goto print4
	BIPUSH 0x4		//   else set second bit of character
	IADD	
print4: ILOAD place		//   place = place << 1
	DUP
	IADD
	ISTORE place
	ILOAD total
	ILOAD place
	IAND			//   if 4th bit of current nibble is zero (total & place)
	IFEQ print5		//     goto print5
	BIPUSH 0x8		//   else set second bit of character
	IADD	
print5: ILOAD place		//   place = place << 1
	DUP
	IADD
	ISTORE place
	GOTO print1
	
pall:   POP			// Pop off leading 0's
	POP
	BIPUSH 0x9
	ISTORE index
pall1:	ILOAD index		// index = index - 1
	BIPUSH 0x1
	ISUB
	DUP
	IFEQ return		// if index = 0  return
	ISTORE index
	DUP
	BIPUSH 0xa		// else if character < 0xa goto pall1
	ISUB
	IFLT pall2
	BIPUSH 0x37		// else convert character to "A"-"F"
	IADD
	OUT			// print character
	GOTO pall1		// goto pall (prepare & print next character)
pall2:	BIPUSH 0x30		// convert character to "0"-"9"
	IADD
	OUT			// print character
	GOTO pall1		// goto pall1 (prepare & print next character)
return:	BIPUSH 0xa		// print cr
	OUT
	IRETURN			// no return value
.end-method

