Assembly Language: Data Conversions Routines

Computer systems use character based keyboards and displays for inputting and outputting data. Conversion routines are necessary to convert data types to character strings and back again.

Consider the entry from a keyboard of an integer value 276. This represents a three character sequence of ‘2’, ‘7’ and ‘6’. This character sequence will need to be converted into an appropriate 16bit value representing an integer. Also consider displaying the value of a byte as two hex digits. Each nibble must be converted to an ASCII character before displaying on the terminal screen.

  • HEX BYTE TO ASCII CHARACTERS

    This routine converts a byte to TWO ASCII characters. eg,

    
    		AFH becomes 41H 46H
    

    The algorithm for this is

    
    		GET DIGIT
    		MASK OFF HIGH NIBBLE 
    		CONVERT TO ASCII 
    		MASK OFF LOW NIBBLE 
    		CONVERT TO ASCII
    

    The following code shows an MC6802 implementation.

    
    		CPU	6802
    		HOF 	MOT 
    		ORG 	0100H 
    	Val1: 	DFB 	3FH 
    	Result:	DFS 	02H 
    		ORG 	120H 
    	Start:
    		LDAA 	Val1 	; get val1 
    		PSHA 		; save val1 
    		ANDA 	#0F0H 	; mask high byte
    		LSRA 		; shift to low nibble 
    		LSRA 
    		LSRA 
    		LSRA 
    		JSR 	Conv 	; convert high nibble 
    		STAA 	Result 	; store it 
    		PULA 
    		ANDA 	#0FH 	; mask low nibble
    		JSR 	Conv 	; convert low nibble 
    		STAA 	Result+1 ; store it 
    	Exit: 	BRA	Exit 
    
    	Conv: 	CMPA 	#9H 	; check for digit 
    		BLS 	ASCZ 
    		ADDA 	#07 	; adjust for letter 
    	ASCZ: 	ADDA 	#30H 	; adjust to ASCII 
    		RTS 
    
    		END 	Start
    
    
  • ASCII STRING TO HEX BYTE

    This routine converts a two character sequence into a hexadecimal byte, eg.

    
    		41H 46H becomes AFH
    

    The algorithm for implementing this routine is,

    
    		Get Digit 
    		Subtract 30H from Digit 
    		If Digit greater than Nine 
    			Subtract 07H from Digit 
    		EndIf
    		Shift into High Nibble and Store 
    		Get Next Digit 
    		Subtract 30H from Next Digit 
    		If Next Digit greater than Nine 
    			Subtract 07H from Next Digit 
    		EndIf 
    		OR Next Digit with stored High Nibble and Store
    

    The following code shows an MC6802 implementation.

    
    		CPU 	6802 
    		HOF 	MOT
    		ORG 	0100H 
    	ASC1: 	DFB 	33H 
    	ASC2: 	DFB 	46H 
    	HexB: 	DFB 	00H 
    		ORG 	120H 
    
    	Start:
    		LDAA 	ASC1 	; get first digit 
    		SUBA 	#30H 
    		CMPA 	#09H 
    		BLS 	If1 
    		SUBA 	#07h
    	If1: 	ASLA
    		ASLA 
    		ASLA 
    		ASLA 
    		STAA 	HexB 
    		LDAA 	ASC2 	; get next digit
    		SUBA 	#30H 
    		CMPA 	#09H 
    		BLS 	If2 
    		SUBA 	#07h 
    	If2: 	ORAA 	HexB 
    		STAA 	HexB
    		END 	Start
    
    
  • 8BIT MULTIPLY

    This routine multiplys two 8bit values together generating a 16bit result. The following algorithm (for two unsigned 8bit values) is based on processors which do
    not have MULTilpy instructions.

    
    		Set Product equal to Zero 
    		Set Counter equal to Eight 
    		While counter not equal to zero 
    			Left Shift Product (Multiply by 2) 
    			Shift Multiplier so bit goes into Carry
    			If Carry bit is Set 
    				Product equals Product plus Multipicand 
    			Endif
    			Subtract one from Counter 
    		EndWhile
    

    The following program implements this for an MC6802.

    
    		CPU	6802 
    		HOF 	MOT 
    		ORG 	0100H
    	Val1: 	DFB 	10H
    	Val2:	DFB 	20H
    	Result:	DFS 	02H 
    		ORG 	0120H
    
    	Start: 	CLRA 			; product MSB = zero
    		CLRB 			; product LSB = zero 
    		LDX 	#0008H 		; multiplier = 8
    	Shift: 	CPX	#0000H 
    		BEQ 	Exit 
    		ASLB 			; shift product left 1 bit 
    		ROLA
    		ASL 	Val1		; shift multiplier left to 
    		BCC 	Decr 		; examine next bit 
    		ADDB 	Val2		; Add multiplicand to 
    		ADCA 	#00H 		; product if carry is set
    	Decr:	DEX
    		BRA 	Shift 		; loop till all 8bits are done
    	Exit: 	STAA 	Result
    		STAB 	Result+1
    	Finish:	BRA	Finish 
    		END 	Start
    
    
  • 8BIT DIVIDE

    This routine divides two 8bit values generating an 8bit quotient and 8bit remainder.The following algorithm (for two unsigned 8bit values) is based on processors which do not have DIVide instructions.

    
    		Set Quotient equal to Zero 
    		Set Counter equal to Eight 
    		While Counter not equal to zero 
    			Left Shift Dividend (Multiply by 2) 
    			Left Shift Quotient 
    			If 8 MSB's of Dividend >= Divisor then 
    				MSB of Dividend = MSB of Divident - Divisor 
    				Add one to Quotient 
    			EndIf 
    			Subtract one from Counter 
    		EndWhile 
    		Remainder = MSB of Dividend
    

    The following program implements this for an MC6802.

    
    		CPU 	6802 
    		HOF 	MOT 
    		ORG 	0100H
    	Val1:	DFB 	10H 		; Dividend
    	Val2: 	DFB 	20H 		; Divisor
    	Quot: 	DFB 	00H
    	Rem: 	DFB	00H 
    		ORG 	0120H
    
    	Start: 	LDX 	#0008H 		; Number of bits in Divisor 
    		CLRA
    		LDAB 	Val1 		; Get Dividend
    	Div: 	CPX 	#0000H 
    		BEQ 	Exit 
    		ASLB 			; Shiftv Dividend and Quotient 
    		ROLA
    		CMPA 	Val2 		; is subtraction successful
    		BCS 	ChkCnt 
    		SUBA 	Val2 		; Yes, subtract and set bit in quotient 
    		INCB
    	ChkCnt:	DEX
    	 	BRA 	Div
    	Exit: 	STAB 	Quot 
    		STAA 	Rem 
    		END 	Start
    
    
  • ASCII TO INTEGER

    This routine converts an ASCII character string into a 16bit signed integer value. To implement this routine, the following variables are used.

    
    		OFFSET	DFB 	;offset into ASCII string 
    		BUFFER 	DFS 	;space for ASCII string 
    		BINV 	DFW 	;integer result 
    		BASE 	DFW 	;base 10 value
    

    The algorithm for implementing the routine is,

    
    		Position Offset to last character in Buffer 
    		Set Base equal to 1 
    		Set BinV equal to zero 
    		While Offset is not zero do 
    			Get Character stored at Buffer[Offset]
    			If character not '-' sign then 
    				Mask out high nibble 
    				Multiply by Base value 
    				Add result to Binv 
    				Base equals Base * 10 
    				Subtract one from Offset 
    			Else 
    				Set HighBit of BinV to 1 
    				Set Offset equal to zero 
    			Endif 
    		EndWhile
    
    
  • INTEGER TO ASCII

    This routine converts a 16bit signed integer into an ASCII character string. To implement this routine, the following variables are used.

    
    		OFFSET	DFB 		;offset into ASCII string 
    		BUFFER 	DFS 		;space for ASCII string 
    		BINV 	DFW 		;integer value 
    		BASE 	DFW 		;base 10 value
    

    The algorithm for implementing the routine is,

    
    		Offset equals last position in Buffer 
    		Get BinV
    		Save BinV value for later use 
    		While BinV not less than 10 
    			Divide BinV by 10 
    			BinV equals remainder added with 30H 
    			Store result at Buffer[Offset] 
    			Offset equals Offset - 1 
    		EndWhile 
    		Add 30H to BinV
    		Store result at Buffer[Offset]
    		Restore original BinV value 
    		If highbit set on BinV 
    			Subtract one from Offset 
    			Store '-' sign at Buffer[Offset] 
    		Endif
    
    
  • PACKED BCD TO DECIMAL

    This routine converts a two digit packed BCD number into an 8bit decimal number. 93 becomes 5DH. The algorithm for performing this is,

    
    		Get Packed BCD Value into Byte 
    		Move High Nibble to Low Nibble of Byte
    		Zero High Nibble of Byte 
    		Multiply Byte by 10 
    		Add Low Nibble of BCD Value to Byte
    

    The following program shows how this is implemented on the MC6802.

    
    		CPU 	6802 
    		HOF 	MOT 
    		ORG 	0100H
    	Val1: 	DFB 	00H
    	Val2: 	DFB 	0AH 		; multiply by 10 decimal
    	Result:	DFS 	02H 		; result of Val1 * Val2
    	PackBCD:DFB	93H
    	DecVal:	DFB	00H
    		ORG	0110H
    
    	Start:	LDAA	PackBCD
    		LSRA 			; shift high nibble to low nibble 
    		LSRA 
    		LSRA 
    		LSRA 
    		STAA 	Val1		; multiply high nibble by 10 
    		JSR 	Multiply 
    		LDAA 	PackBCD 
    		ANDA 	#0FH		; mask high byte 
    		ADDA 	Result+1 	; add to high byte * 10 
    		STAA 	DecVal		; store decimal value
    	Finish:	BRA 	Finish
    	
    	Multiply:	CLRA		; product MSB = zero 
    		CLRB 			; product LSB = zero 
    		LDX 	#0008H 		; multiplier = 8
    	Shift:	CPX 	#0000H 
    		BEQ 	Exit 
    		ASLB 			; shift product left 1 bit 
    		ROLA
    		ASL 	Val1 		; shift multiplier left to 
    		BCC 	Decr 		; examine next bit
    		ADDB 	Val2 		; Add multiplicand to 
    		ADCA 	#00H 		; product if carry is
    	setDecr:	DEX
    		BRA	Shift 	; loop till all 8bits are done
    	Exit: 	STAA	Result 
    		STAB 	Result+1 
    		RTS 
    		END 	Start
    
    

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.