hex convert long number

elektriker

New Member
Hello,
how can I have a number string "987654321" in hex convert (= hex(3ADE 68b1)
can someone help me?

many thanks
 

AllyCat

Senior Member
Hi,

That's not easy because PICaxe only works (easily) with numbers up to 16-bits, i.e. $FFFF or 65535.

The first stage is to convert the decimal string into binary. Suppose (for your example), b1 = 1, b2 = 2, b3 =3, etc., then the binary word is given by: W0 = (b3 * 100) + (b2 * 10) + b1 . But PICaxe can't use brackets and always calculates from left to right, so the formula becomes: W0 = b3 * 10 + b2 * 10 + b1 , which can easily be extended up to 5 digits (one word = two bytes).

Next you need to split the word/bytes into nybbles of 4 bits. W0 is the same as b1:b0, so the 4 hex bytes can be calculated as: b4 = b1 / 16 : b3 = b1 // 16 : b2 = b0 / 16 : b1 = b0 // 16 . Finally, you can convert to ASCII format characters using: LOOKUP b1,("0123456789ABCDEF"),b1 for each nybble, then print it with SERTXD("$",b4,b3,b2,b1,cr,lf).

For larger numbers you will have to create your own "long word" format, perhaps using @bptr (or PREEKs and POKEs). You probably need only long word addition, because the multiplications are only up to * 9, so can be done with repeated addition in a FOR ... NEXT loop.

There are several threads on the forum (and in code snippets) concerning long word processing, but you might find post #2 in my thread here of some help.

Cheers, Alan.
 

hippy

Technical Support
Staff member
I must admit that it wasn't clear to me if what's wanted is to convert a decimal number into hex or vice-versa.

In either case, part of answering the question would be needing to know in what format the data is in when passed to the program which has to do the conversion.
 

elektriker

New Member
Thank you, Allycat, westaust55 and hippy.

how can I have a number string "987654321" in Bin ( 32bit --> Word_Hi; Word_Lo) convert?
the dec-number is in : b1=1: b2=2: ... b8=8: b9=9
i can not find a examble in the Forum.

many thanks
 

AllyCat

Senior Member
Hi,

Since nobody else has answered, the following works exactly as I described in #2. There may be better or faster methods and it's not intended to be a model of perfect programming, but it does seem to give the correct answer (in the simulator). Also note that it assumes that all registers have been reset to zero at the start! :

Code:
b1 = 1 : b2 = 2 : b3 = 3 : b4 = 4 : b5 = 5 : b6 = 6 : b7 = 7 :b8 = 8 : b9 = 9

symbol Hexptr = b10
symbol Sumptr = b11
symbol Incptr = b12
symbol Decval = b13
symbol IncLW = 32						; Increasing decimal value (in binary format)
symbol SumLW = 40						; Present decimal value (in binary format)
symbol HexLW = 48						; Accumulating decimal value (in binary format)

	poke  IncLW,1						; Initialise Increment (Higher word must be clear)
	poke  SumLW,1 						; Initialise Sum (Higher word and Hex words must be clear)
	for bptr = 1 to 9
		for Decval = 1 to 9
			if @bptr = Decval then	; Add decimal value into binary field
				Sumptr = HexLW			; Running total
				Incptr = SumLW			; value to add 
				call sum					; Result returned at Sumptr
			endif	
			Sumptr = SumLW				
			Incptr = IncLW
			call sum				; Next decimal value (in binary format),ie: 1,2..9,10,20..90,100,200..
		next
		sumptr = sumlw
		incptr = inclw			
		peek Sumptr,b0 : poke Incptr,b0 : inc Sumptr : inc Incptr	; Copy sum to next increment
		peek Sumptr,b0 : poke Incptr,b0 : inc Sumptr : inc Incptr
		peek Sumptr,b0 : poke Incptr,b0 : inc Sumptr : inc Incptr
		peek Sumptr,b0 : poke Incptr,b0 
	next
	sertxd("$")
	bptr = HexLW + 3
	do
		b0 = @bptr / 16 
		lookup b0,("0123456789ABCDEF"),b0
		sertxd(b0)
		b0 = @bptrdec // 16 
		lookup b0,("0123456789ABCDEF"),b0
		sertxd(b0)
	loop until bptr < HexLW
	sertxd(cr,lf)
;; Result Should be = 3ADE68B1 
end
sum:
	peek Sumptr,b14,b15,b16,b17		; Read w8:w7 (Hi:Lo)
	peek Incptr,b18,b19,b20,b21		; Read w10:w9
	w7 = w7 + w9							; Add Low words
	w8 = w8 + w10							; Add High words
	if w7 < w9 then 						; Carry to high word
		inc w8
	endif
	poke Sumptr,b14,b15,b16,b17		; Store sum
	return
Cheers, Alan.
 

BillBWann

Member
There may be better or faster methods......
Somewhat belatedly, I rose to AllyCat’s implied challenge to write faster, more efficient code to achieve this conversion. My program uses the method outlined by AllyCat in #2 (b9*10+b8*10+b7*10...+b1). It has sub-routines for both long word addition and multiplication and only requires 3 bytes of memory (b0 &TempW) in addition to the initial digits (b1-b9), and the long word answer(Word_Hi:Word_Lo) which needs to be initially zero.

The actual conversion code space is quite small (only 63 bytes long) and the conversion time should be significantly faster.

This code hasn’t been extensively tested but seemed to give the correct answer (in the simulator) for the values tested.

Code:
#picaxe 08m2
#no_data

symbol Word_Lo=w5
symbol Word_Hi=w6
symbol TempW=w7	'Temporary working word
symbol TempL=b14	'Low byte of working word
symbol TempH=b15	'High byte of working word

symbol PLSB=10	'Pointer to LSB of long word
symbol PMSB=PLSB+3	'Pointer to MSB of long word


b1 = 1 : b2 = 2 : b3 = 3 : b4 = 4 : b5 = 5 : b6 = 6 : b7 = 7 :b8 = 8 : b9 = 9
'b1 = 7 : b2 = 3 : b3 = 5 : b4 = 5 : b5 = 6 : b6 = 0 : b7 = 0 :b8 = 0 : b9 = 0

poke PLSB,b9	'Add most significant digit to long word (assumes long word is zero initially)

for b0=8 to 1 step -1	'Consecutively multiply by 10 and add to long word for each of the remaining digits
	call LongWordMult10
	bptr=b0
	TempH=@bptr
	call LongWordPlusByte
next b0

bptr=PMSB	'Print out the result
sertxd("$")
do
	b0=@bptr/16
	call PrtNib
	b0=@bptrdec and $F
	call PrtNib
loop until bptr<PLSB
;; Result Should be = 3ADE68B1 
end

'-----------------------------------------------------------------
LongWordMult10:
'Multiplies the long word (Word_Hi:Word_Lo)*10
bptr=PLSB
TempH=0
do
	TempW=@bptr*10+TempH
	@bptrinc=TempL
loop until bptr>PMSB
return

'-----------------------------------------------------------------
LongWordPlusByte:
'Adds TempH to the long word (Word_Hi:Word_Lo)
bptr=PLSB
do
	TempW=@bptr+TempH
	@bptrinc=TempL
loop while TempH>0
return

'-----------------------------------------------------------------
PrtNib:
'Print the Hex character contained in the low nibble of b0 
if b0<10 then
	b0=b0+"0"
else
	b0=b0+"A"-10
endif
sertxd (b0)
return
 

elektriker

New Member
Hello BillBWann.

Your program works quickly and accurately.
One question I have:
How can you extend this code to 10 decimal places (= in binary 2^32)?
Which line should I delete, so I do not get any hex dump, but only decimal to binary (hiword and LoWord)?

thank you very much
 

BillBWann

Member
How can you extend this code to 10 decimal places (= in binary 2^32)?
The largest decimal number that can be converted to a 32 bit binary number is 4,294,967,295 so it isn’t possible to convert all 10 digit decimal numbers. If the first digit will never exceed 3 then there won’t be a problem except that space will need to be made to store this extra digit - in b10 presumably which will mean that the location of the long word will need to be moved up a bit.

If you want to represent all 10 digit decimal numbers, then you’ll need to go to, at least, a 5 byte long word and I wrote the program so that this could be easily achieved.


Which line should I delete, so I do not get any hex dump, but only decimal to binary (hiword and LoWord)?
If you don’t want to get a hex print out of the long word (HiWord & LoWord), simply delete lines 29-37 (commencing with bptr=PMSB....) - the binary number is stored in bytes b10,b11,b12,b13 with b10 containing the LSB.

If you’d like me to adjust the program to allow for all 10 digit numbers, let me know how many bytes you want to assign to your binary long word (5 or 6) and I’d be happy to do it for you.
 
Top