 # 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
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
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
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

```