PASM Coding help: Integer to ASCII - ASCII to Integer
Can some one point me to a resource for converting an integer to ASCII and an ASCII string to an integer using PASM? I knocked this conversion out in SPIN without much effort. For some reason converting SPIN to PASM has got me reeling. I think my base 10 SPIN approach is clogging up my thought process.

Comments
http://www.asciitable.com/index/asciifull.gif
And conversion to binary,,,
http://www.ascii.cl/conversion.htm
dec_to_ASCII 'Converts an unsigned number in a register to an ASCII value 't1 - The decimal number 't2 - The current count of the digits (ie, how many 100's are in 843) 't3 - The current number of digit (1000(4), 10(2), 1(1)) 't4 - (parameter) the number to convert 't5 - (parameter) the number of digits in the number (modified) ' ---too few will result in tuncation of upper digits 'ASCII_num - (result) will contain the number, optional negative (-, counts as digit) movs :main_loop, #decimal movd :write, #ASCII_num mov t3, #10 :main_loop mov t1, 0-0 'Copy the decimal number (1, 1000, 10000, etc) into the variable mov t2, #0 'Clear the counter :multiply cmp t4, t1 wc 'Is the number less than the decimal number? if_nc sub t4, t1 'The decimal number is <= than the value if_nc add t2, #1 'increment the digit count if_nc jmp #:multiply add t2, #48 'Increase to ASCII 0 :write mov 0-0, t2 cmp t5, t3 wc 'Should I write move on to the next digit? if_nc add :write, destination_mask'Move on to the next digit in ASCII_num add :main_loop, #1 'Move on to the next digit in decimal djnz t3, #:main_loop dec_to_ASCII_ret retASCII_to_dec 'Routine to convert a string of ASCII numbers to decimal 'Takes two parameters: ' a) the string (in long array ASCII_num) ' b) the length (in long ASCII_num_length, 1<=length<=9) 'The array is stored MSD first. For example: 'The number 756 is stored like: 'ASCII_num 7 ' 5 ' 6 'Supports up to 9 digits 'Algorithm: convert from number from right to left (6, 5, 7) ' 'Returns 0 if there isn't a number (aka, ASCII_num_length == 0) ' 'Result is in t5 't6 is the pointer to the current ASCII digit 't7 is the current ASCII digit value (ASCII 6 - #48, for example) mov t5, #0 'clear the result register mov t6, #ASCII_num add t6, ASCII_num_length movs :loop, t6 'Set the loop mov to the current ASCII digit sub :loop, #1 'First number is at position n-1 cmp ASCII_num_length, #0 wz 'test to make sure that there is actually a number if_z mov t5, #0 'if there isn't a number, return 0 if_z jmp :done :loop mov t7, 0-0 'Copy the ASCII number (0-0 will point to ASCII_num) sub t7, #48 wz 'Subtract an ASCII '0' (zero) from the current digit sub :loop, #1 'Move pointer down for next time if_z add :mult_loop, #1 'increment to the next decimal number if it's a zero if_z djnz ASCII_num_length, #:loop 'if the number is zero, skip this digit and get the next if_z jmp #:done 'if the number is zero, and it's the last one go to done :mult_loop add t5, decimal 'Add the decimal (10, 1_000, etc.) to the result (will be self-modified in source) djnz t7, #:mult_loop 'Decrement one from the ASCII placeholder, keep looping if more add :mult_loop, #1 'move to next decimal up djnz ASCII_num_length, #:loop :done movs :mult_loop, #decimal ASCII_to_dec_ret retFrom two different objects that I wrote. May not be symmetric. Also not really tuned for efficiency (memory or speed), although it should be reasonable for most cases.
This is what I came up with. It looks a lengthy compared to SRLM's version. This exercise was much more involved than I thought; self-modifying code, division, looping...
If Johnny Mac is out there... Integer to ASCII could make a good Spin Zone article?
DAT org 0 entry mov t1, par ' points to command mov cmdptr, t1 ' save pointer to command add t1, #4 mov rsltptr, t1 ' save result pointer getcmd rdlong cmd, cmdptr wz ' Wait until the command is not zero '***debug result ***** rdlong rslt, rsltptr ' testing '***debug result ***** if_z jmp #getcmd switch_cmd cmp cmd, #1 wz if_e jmp #cmdset cmp cmd, #2 wz if_e jmp #toascii cmp cmd, #3 wz if_e jmp #match jmp #getcmd ' default jump cmdset jmp #getcmd ' Reset the command '------------------------------------------------------------------------- ' Number to ASCII '------------------------------------------------------------------------- toascii add t1, #4 ' next hub long rdlong srcptr, t1 ' source string pointer mov i, #0 ' init counter rdlong srcobj, srcptr ' grab the number to convert add t1, #4 ' next hub long rdlong dstptr, t1 ' destination string pointer :_main movd :buffer, #workspace ' initialize destination (buffer) address mov x, srcobj ' get source number to convert :loop mov y, #10 ' set divisor = 10 call #divide ' divide routine mov t1, x ' save remainder[31..16] and quotient[15..0] shr t1, #16 ' shift the remainder to [15..0] shl x, #16 ' get quotient by shifting out the remainder shr x, #16 ' shift back to [15..0] add t1, #$30 ' convert the remainder to an ascii char :buffer mov 0-0, t1 ' stick the char in the cog buffer add :buffer, incr ' increment the buffer pointer add i, #1 ' count the items in the buffer cmp x, #0 wz ' are we done? if_ne jmp #:loop ' no = loop; yes = finish conversion mov t1, #workspace ' set up the cog buffer pointer add t1, i ' go to the end of the buffer sub t1, #1 ' note: the chars are in reversed in the buffer write_to_hub movs :readbuff, t1 ' set the source pointer :loop sub i, #1 ' decr buffer item counter :readbuff mov t1, 0-0 ' get a byte from the buffer wrbyte t1, dstptr ' write the byte to hub memory add dstptr, #1 ' increment hub memory pointer sub :readbuff, #1 ' decrement cog pointer cmp i, #0 wz ' are we done? if_ne jmp #:loop ' false = get next; true = finish up :done mov dstobj, #0 ' get terminating zero (0) wrbyte dstobj, dstptr ' write 0 to hub memory :rtn wrbyte i, rsltptr ' write result to hub wrlong zero, cmdptr ' clear command jmp #getcmd ' reset '--- Functions ----- ' Divide x[31..0] by y[15..0] (y[16] must be 0) ' on exit, quotient is in x[15..0] and remainder is in x[31..16] ' This code is from the Propeller Manual Appendix B divide shl y,#15 'get divisor into y[30..15] mov t,#16 'ready for 16 quotient bits :loop cmpsub x,y wc 'y =< x? Subtract it, quotient bit in c rcl x,#1 'rotate c into quotient, shift dividend djnz t,#:loop 'loop until done divide_ret ret 'quotient in x[15..0], 'remainder in x[31..16] ' ' Variables ' maxcnt long $800 incr long 1<<9 '--------- t1 long 0 t2 long 0 t3 long 0 t4 long 0 zero long 0 '--------- i long 0 j long 0 '--------- cmdptr long 0 srcptr long 0 patptr long 0 dstptr long 0 '--------- cmd long 0 srcobj long 0 patchr long 0 dstobj long 0 '---------- rslt long 0 rsltptr long 0 '---------- offst long 0 binry long 0 '---------- x long 0 y long 0 t long 0 '---------- workspace res 16 fitNext up, ASCII to integer. Should be a little easier, I hope.
Essentially, it works by shifting the hex value left into a destination register one bit at a time, and adding 3 to any nibble of the destination that is greater than 4.
{{ BCD Hex Start 0000_0000|0111_1011 = $7B = 123 1 Shift left 0|1111_011 2 Shift left 01|1110_11 3 Shift left 011|1101_1 4 Shift left 0111|1011 Add 3 1010|1011 5 Shift left 1_0101|011 Add 3 1_1000|011 6 Shift left 11_0000|11 7 Shift left 110_0001|1 Add 3 1001_0001|1 8 Shift left 1 0010_0011| = $0123 }} Hex_to_BCD mov BCD_Value,#00 mov BitCtr,#32 ' Count 32 bits to shift :Outer_Loop mov NibCtr,#8 ' Rotate eight nibbles in BCD_Value :Nibble_Loop rol BCD_Value,#4 ' Rotate high nibble into low nibble location mov Temp,BCD_Value ' Copy rotated value and Temp,#$0F ' Mask the low nibble cmp Temp,#05 wc ' Is masked value greater than 4? if_nc add BCD_Value,#03 ' Add three if nibble is greater than 4 djnz NibCtr,#:Nibble_Loop ' Loop until all eight nibbles are checked shl Hex_Value,#1 wc ' Shift msb out of Hex_Value into C rcl BCD_Value,#1 ' Rotate C into BCD_Value djnz BitCtr,#:Outer_Loop ' Loop until all 32 bits of long are shiftedThis converts the hex value into BCD, packed one digit per nibble. From here you'd just take the nibbles one at a time, add an ASCII offset of $30, and send to the LCD. The above routine can handle a decimal value of up to 99,999,999, any more than that and you'll need to modify it to use two longs for the destination.The algorithm works just as well in reverse to convert decimal back into hex, shifting the BCD value right one bit at a time into the destination, still checking all nibbles of the BCD value and subtracting 3 from any nibble that is greater than 4.
So you have a 32bit data in memory, of course that is binary data.
And that we can also see it as dec and hex is just alternative version that
'data viewer' / assembler shows it.
Converting this binary to a 8 digit ascii hex would be great start.
unfortunately ascii A-F does not follow directly after 0-9
So either create a look up table, or with some controlled additions.
non tested code: mov buffer, data 'data have the original 32bit value. movd label, #myhex mov counter, #8 loop mov buffer2, buffer and buffer2, #%1111 'just get the lower 4 bits a 0-F value. add buffer2, #48 'bring it up to ascii code for 0 cmp buffer2, #58 wc 'was it higher that 9? if_c add buffer2, #7 'make it A-F label mov 0-0, buffer2 add label, _my9 ror buffer,#4 'shift nibble dnjz counter, #loop _my9 long 1<9 myhex res 8 buffer res 1 buffer2 res 1 counter res 1This should set 8 longs to ascii hex,
if you want reversed order use #myhex+8 and use sub label, _my9
if you want 8 bytes in 2 longs when it would need more coding.
can you please email me the spin code of integer to ASCII conversion for propeller?
my email is at_jay@yahoo.com.
Thanks
Jay
I couldn't find FullDuplexSerialPlus in the Object Exchange. Maybe it's part of some other package (like the Propeller Education Kit software). In any event, I've attached my copy of it.