• AVR Freaks

Hot!Bin2Hex

Author
upand_at_them
Super Member
  • Total Posts : 584
  • Reward points : 0
  • Joined: 2005/05/16 07:02:38
  • Location: Pennsylvania
  • Status: offline
2020/05/16 08:13:59 (permalink)
0

Bin2Hex

I found this routine on piclist:

 movwf char_hi
swapf char_hi,w
andlw 0x0f

addlw 6
skpndc
addlw 'A'-('9'+1)
addlw '0'-6

xorwf char_hi,w
xorwf char_hi,f
xorwf char_hi,w

andlw 0x0f

addlw 6
skpndc
addlw 'A'-('9'+1)
addlw '0'-6
return

 
Touted as "15 cycles".  But I'm using a shorter routines (got the method on MC forum):

movwf d1
andlw 0x0f ; separate the digit
addlw 0xf6 ; compare to 10
skpnc ; if 9 or less, skip the following addition
addlw 0x7 ; for 10, we need 'A' (0x41) instead of 0x3a, so add 7
addlw 0x3a ; add back 10 and convert to ASCII
movwf d0

swapf d1, w
andlw 0x0f ; separate the digit
addlw 0xf6 ; compare to 10
skpnc ; if 9 or less, skip the following addition
addlw 0x7 ; for 10, we need 'A' (0x41) instead of 0x3a, so add 7
addlw 0x3a ; add back 10 and convert to ASCII
return

 
The second one is so much better in my opinion.  It's faster and consumes less program memory.  It also leaves the MSD in W, which saves a MOV instruction in the "print" routine.  The first routine looks unnecessarily confusing.  Does it have some benefit?  I can only see that it uses just one RAM location, but it leaves the wrong digit in W on exit.
post edited by upand_at_them - 2020/05/16 08:16:12
#1

6 Replies Related Threads

    1and0
    Access is Denied
    • Total Posts : 10999
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Bin2Hex 2020/05/16 11:23:36 (permalink)
    0
    upand_at_them
    The second one is so much better in my opinion.

    That depends on what you want to optimize for -- RAM or ROM.
     

    It's faster and consumes less program memory.

    A lookup table may be faster, at the expense of more program memory.
     

    It also leaves the MSD in W, which saves a MOV instruction in the "print" routine.

    The former stores the LSD in WREG. ;)
     

    The first routine looks unnecessarily confusing.

    It's similar to the second routine.
     

    Does it have some benefit?  I can only see that it uses just one RAM location,

    Exactly. ;)
     

    but it leaves the wrong digit in W on exit.

    No, the first routine stores the LSD in WREG, while the second routine stores the MSD in WREG.
     
    With that said, I think Bin2Hex is the wrong name for these routines -- the result is in ASCII; i.e. it is basically utoa() with radix hex.
     
     
    #2
    1and0
    Access is Denied
    • Total Posts : 10999
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Bin2Hex 2020/05/16 12:19:55 (permalink)
    5 (1)
    upand_at_them
    addlw 6
    skpndc
    addlw 'A'-('9'+1)
    addlw '0'-6

    addlw 0xf6 ; compare to 10
    skpnc ; if 9 or less, skip the following addition
    addlw 0x7 ; for 10, we need 'A' (0x41) instead of 0x3a, so add 7
    addlw 0x3a ; add back 10 and convert to ASCII

    The first routine looks unnecessarily confusing.

     
    One more thing, actually the second routine looks more confusing because it uses magic numbers, instead of using recognizable constants and let the assembler does the calculations.
     
    post edited by 1and0 - 2020/05/16 12:22:44
    #3
    upand_at_them
    Super Member
    • Total Posts : 584
    • Reward points : 0
    • Joined: 2005/05/16 07:02:38
    • Location: Pennsylvania
    • Status: offline
    Re: Bin2Hex 2020/05/16 12:32:00 (permalink)
    0
    I can be forgiven...I copied it from a thread on here. :)
     
    After thinking on it a bit, I came up with a shorter version (if a person needed such a thing):
     
    Bin2HexAscii ; routine enters with value in W, exits with MSD in W
     
    movwf d1
    call Bin2HexNibble
    movwf d0
    swapf d1, w
    Bin2HexNibble
    andlw 0x0f ; separate the digit
    addlw 0xf6 ; compare to 10
    skpnc ; if 9 or less, skip the following addition
    addlw 0x7 ; for 10, we need 'A' (0x41) instead of 0x3a, so add 7
    addlw 0x3a ; add back 10 and convert to ASCII
    return

    post edited by upand_at_them - 2020/05/16 12:33:25
    #4
    1and0
    Access is Denied
    • Total Posts : 10999
    • Reward points : 0
    • Joined: 2007/05/06 12:03:20
    • Location: Harry's Gray Matter
    • Status: offline
    Re: Bin2Hex 2020/05/16 16:17:13 (permalink)
    5 (1)
    upand_at_them

    addlw 0xf6 ; compare to 10
    skpnc ; if 9 or less, skip the following addition
    addlw 0x7 ; for 10, we need 'A' (0x41) instead of 0x3a, so add 7
    addlw 0x3a ; add back 10 and convert to ASCII


    Replace the above with this
            radix   dec
     
            addlw   -10
            skpnc
            addlw   'A' - ('0' + 10)
            addlw   '0' + 10

    which is self-documented. ;)
     
     
    #5
    du00000001
    Just Some Member
    • Total Posts : 3848
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: Bin2Hex 2020/05/16 16:40:44 (permalink)
    4 (1)
    upand_at_them
    I can be forgiven...I copied it from a thread on here. :)
     
    After thinking on it a bit, I came up with a shorter version (if a person needed such a thing):
    ...



    Shorter (in terms of code size) yes. But even slower than the first version.
    As usual, it depends on whether you're optimizing for code size, execution speed and/or RAM consumption . . .

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #6
    upand_at_them
    Super Member
    • Total Posts : 584
    • Reward points : 0
    • Joined: 2005/05/16 07:02:38
    • Location: Pennsylvania
    • Status: offline
    Re: Bin2Hex 2020/05/16 17:20:09 (permalink)
    0
    Yes.  I'm not using that shorter version, for that reason.
    #7
    Jump to:
    © 2020 APG vNext Commercial Version 4.5