One possible method is that we'll take each bit's decimal value and add this to the result. We would have to add the folowing numbers:

Bit | If 1 add |
---|---|

0 | "001" |

1 | "002" |

2 | "004" |

3 | "008" |

4 | "016" |

5 | "032" |

6 | "064" |

7 | "128" |

Much simpler than this is to repeatedly subtract decimal 100 from the number until a carry occurs. The number of times, where the carry is not one, is either zero, one or two, and is the first digit of the result.

We can then repeat that with subtracting tens from the number. The number of times, we can subtract the ten without a carry can be between zero and nine, and is the second digit.

The third digit is simply the rest of the number left, we can simply convert this rest to ASCII and we're done.

It starts with setting a register (here: R16) to the desired binary value. Just add the directive

The second step is to define the target, where the result goes to. Here, we use a pointer in the register pair X to point to a location in SRAM. To prepare this, we use the following directives:

```
.dseg
sD:
.byte 3
.cseg
```

The SRAM is now prepared to receive the three-digit-ASCII-string.
Then follows the first subtraction loop. We set a counter, but we do not set it to zero. We set it to the ASCII character before the ASCII zero (the ASCII zero would be decimal 48), but we use '0' minus 1 as starting point. The loop, that starts with increasing the counter, now in its first execution sets the result byte to ASCII '0'. If the following subtraction of decimal 100 already ends with the carry flag set (if the number is smaller than 100), the result byte is '0'. If not, the loop is further repeated, until that is the case.

The last subtraction yielded a carry, so we have to undo this. As the assembler for AVRs does not have an ADDI instruction, we use SUBI, but with -100. That does virtually the same, but with a slightly different flag setting (which we don't need in our case).

The counter in R17, which is now either '0','1' or '2', is then written with an ST instruction to the SRAM location. The pointer is auto-incremented after the write operationandalready points to the next loaction in SRAM.

Now the loop with the subtraction of decimal ten follows. Again we start the counter with '0' minus one, but now we SUBI ten from the number. If no carry happens, we repeat the subtraction. After carry we again undo the last operation and write the second digit to the store.

The rest of the number is then converted to ASCII by adding 48. As there is no ADDI, we again use SUBI, but with -'0'. This last digit is written to the store and we are complete.

Here, the first three instructions of the source code have been executed. Register R16 has the number to be converted, the pointer register X points to the beginning of the SRAM.

Here, the first loop subtracting 100 has been executed and the result, an ASCII character '1' has been written to SRAM.

The second loop, subtracting 10 from the number, has been executed and the second digit has been written to SRAM.

And the last two instructions have produced the third digit in SRAM.

Here are the execution times: to the left with 123, to the right with 190. The times are not too different (factor of two, all well below 1 ms).

This is the simulation with the leading zeros blanked. Of cource, the number converted here was zero.

As best choice for that we can use the T flag from SREG. If the 100s aren't zero, we clear the T flag, otherwise set it.

Before checking the tens for zero, we ask the T flag with BRTC if this flag is clear. If so, the zero check is jumped over and not executed.

This variation is activated if the constant

To the page top

©2022 by http://www.avr-asm-tutorial.net