Scott Dattalo and Dmitry Kiryashov
;ascii1 and ascii2 are the tens and ones digit of a number we wish
;to convert to binary
;
; In C:
;
; binary = (ascii1 & 0xf) * 10 + (ascii2 & 0xf);
;
; (I'd be interested to see how a compiler would generate the asm for this.)
;
;Clear the upper nibble of the one's digit
mov W, #$0f
and ascii2, W
;Multiply the tens digit by 10.
mov W, <<ascii1 ;2*tens
;Note that the carry is also cleared because
;ascii1 is an ASCII number between 0x30-0x39
and W, #$1e ;Clear upper nibble of tens digit
;In addition, we clear the shifted in carry
mov ascii1, W ;W = ascii1 = 2*original ascii1
rl ascii1 ;ascii1 = 4*original ascii1
rl ascii1 ;ascii1 = 8*original ascii1
add W, ascii1 ;W = 2*original ascii1 + 8 *original ascii1
; = 10*original ascii1
;add the one's digit
add W, ascii2 ;
; Or use this one that preserves input:
mov W, <<tens
and W, #$1e ;w=2*tens
mov temp, W
rl temp ;temp=4*tens
rl temp ;temp=8*tens
add temp, W ;temp=8*tens+2*tens=10*tens
mov W, #-'0' ;convert one's digit from ASCII to decimal
add W, ones ;w=ones
add W, temp ;w=ones+10*tens
;Dmitry Kiryashov [zews at AHA.RU] says:
;Destructive way to save one more clock ;-)
mov W, tens ;*1 w=0x30..0x39
add tens, W ;*2 tens=0x60..0x72
rl tens ;*4 tens=0xC0..0xE4
add tens, W ;*5 tens=0xF0..0x1ED
mov W, #(-11*'0') & $FF ;low byte of -48*11
add W, ones
add W, tens ;add two times tens=5*original_tens
add W, tens
;Why so ? tens is '0' + x , ones is '0' + y , where x and y are in range
;of 0..9 So finally '0'*(10+1)=48.*11.=528.=0x210 . it is constant so we
;can subtract it back from result. Here we gone ;)