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.)
;
movlw 0x0f
andwf ascii2,f ;Clear the upper nibble of the one's digit
; Multiply the ones digit by 10.
rlf ascii1,w ;2*tens
;Note that the carry is also cleared because
;ascii1 is an ASCII number between 0x30-0x39
andlw 0x1e ;Clear upper nibble of tens digit
;In addition, we clear the shifted in carry
movwf ascii1 ;W = ascii1 = 2*original ascii1
rlf ascii1,f ;ascii1 = 4*original ascii1
rlf ascii1,f ;ascii1 = 8*original ascii1
addwf ascii1,w ;W = 2*original ascii1 + 8 *original ascii1
; = 10*original ascii1
addwf ascii2,w ;
; Or use this one that saves a cycle:
rlf tens,w
andlw 0x1e ;w=2*tens
movwf temp
rlf temp,f ;temp=4*tens
rlf temp,f ;temp=8*tens
addwf ones,w
addlw -'0' ;convert from ASCII to decimal
;w=tens*2 + ones
addwf temp,w ;w=10*tens + ones
;Dmitry Kiryashov [zews at AHA.RU] says:
;Destructive way to save one more clock ;-)
movfw tens ;*1
addwf tens,F ;*2
rlf tens,F ;*4
addwf tens,F ;*5
rlf tens,W ;*10
addwf ones,W
addlw low -11.*'0'
;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 ;)