converting string to int assembly

Thread Starter

snr

Joined Mar 14, 2016
6
I have been trying to write the code on HCS12 for hours . My algorithm is that read the string char-by-char, subtract #$30, which means '0' and hold it in a address. Hold another random address in which is filled by 0. Then until end of the string, multiply by 10 content of the random address and add content of the address which is used to convert int by subtracting #$30. I'm really exhausted and hard to implement my algorithm. By the way, I don't know whether it is possible but, I think I can't use default multiplier EMUL, because it uses and writes onto Y and D registers.

Some pseudos:
Code:
num = num*10 + conv(next digit).
var * 10:
res = var
res << 1 (shift left)
res << 1
res = res + var
res << 1

Now res equals var*10
My stucked code:
Code:
MYSTR FCC "1337"
Entry:

LDX #MYSTR
CLRA
STAA $1900 ; random address
loop:
LDAA 1, x+ ; pointer to string
CMPA #0 ; check end of string
BEQ halt ; if end of string end the program
BRA atoi ; num in accumulator A is converted to int
;BRA halt

atoi:
STAA $1300
LDAB $1300
SUBB #$30
;----- number - '0' converts to int
JSR mult
BRA loop

mult:
CLRB
STAB $1350
MOVB $1350, $1351 ; copy content of 1350(var) to 1351(res)
ASL $1351
ASL $1351
LDAA $1351
ADDA $1350 ; res += var;
ASLA ; res << 1

RTS

halt:
SWI
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,719
The general method you are using multiplies the result by 10 then adds the new digit (0-9). I don't see that your code does that but I'm not too up on HC12 code these days either. I think your shift / accumulate operations are out of order.

Also, make sure you are using the 16 bit register designations and not confusing with the 8 bit ones. For example, ASL shifts an 8 bit register, not 16 bits if I read the instruction set right. Your test number won't fit in 8 bits. ASLD may be what you are looking for - it shifts the A and B accumulators as a 16 bit register called D.

The digit by digit accumulation procedure to variable n is

n = (n*10) + new_digit.

The multiplication is performed as (n*10) = (n*8) +( n*2)

To do that:
Shift n left once (n*2) and store that shifted result in a temp register ( n*2-> temp)
Shift n left 2 more times (n*8)
Add the temp register to the shifted n: (n*8)+(n*2), now n is multiplied by 10.
Add the new digit (0-9) to n.

If you have big numbers, you'll need to make n and temp big enough, 16 bits for an int (0-65535) and do double precision shifts and adds. I've attached some PIC assembler code (BCD2BIN.asm) that uses that *10 method, FWIW.

I think I can't use default multiplier EMUL, because it uses and writes onto Y and D registers.
I don't know why not. I think you are trying to keep everything in the registers when you should have it in RAM and use the registers for temp arithmetic. For example:
Keep n in a 16 bit variable in RAM.
c is the new digit in RAM(converted from ASCII )


To add the new character:
Move n (16bits) from RAM to index register Y (16 bits)
Clear A, load B with 10decimal. (making D double accumulator made up of A|B = 10 i.e. $000A).
EMUL ; Y*D = Y|D 16x16=32 bit result, D is the LS16 bits that you want - if Y<>0, its an overflow,
D (A|B combined) = n*10 16 bits

ADDB c ; add the 8 bit character in RAM to B
BCC no_cy ; if no carry, done
INCA ; else, propagate carry to A
no_cy:
STD n ; store 16 bit double accumulator A:B to n, the result


If you stored the new digit as 16bits (00 0d), you could make the addition easier by using
ADDD c ; double accumulator AB += c
instead of the 8 bit add and propagate carry. Lots of ways to skin this.

Don't forget that you can PUSH registers on the stack for temporary storage - PUL to a register to use and be sure each PUSH has a corresponding PUL before the return.

Finally, try to use equates in your code rather than literal values e.g. $1300. Its much easier to see what's going on and you are more likely to succeed.

Good luck and welcome to AAC!
EDIT: Removed double dabble method; Confusing the issue.
 

Attachments

Last edited:
Top