```
.equ number=3/2
```

The constant NUMBER is not 1.5, as expected. Instead the assembler
gavrasm lists the following in its listing:
List of symbols: Type nDef nUsed Decimalval Hexval Name C 1 0 1 01 NUMBER(Note: the list of symbols is generated by the assembler gavrasm only, other assemblers don't have that feature!)

Instead of 1.5 there is a one in the constant

That results from the fact that assembler can only handle integers. That makes sense in the binary world: if only zeroes and ones are available, no half, quarter or tenth are available. Those who try to introduce broken decimals into assembler, in order to allow C-Programmer's unwillingness to learn and understand, produces nonsense: the divider in a timer can only handle integers and can never divide by 1.5!

```
.equ number=(3+1)/2
```

Prior to dividing by two we'll have to add half of the divider. Only
that brings rounding-up the result, and our constant will be 2:
List of symbols: Type nDef nUsed Decimalval Hexval Name C 1 0 2 02 NUMBERWhen calculating more complex expressions, a separate constant holding the divider only can be recommended. Take as an example the calculation of the frequency of a divided clock in a timer. The prescaler divides the clock by e. g. 64 and the timer divides it by 15. We assume further that the timer toggles an output pin when he reaches 15 and clears. That makes an additional division by two. With

```
.equ divider=15*64*2
```

we calculate the whole divider rate, by which the divider divides
the controller's clock frequency.
If the controller works at a clock rate of 1 MHz, the resulting frequency will be, rounded up, as follows:

```
.equ frequency = (1000000 + divider/2) / divider
```

The rule that * and / has a higher priority than + and - causes that
we do not have to place divider/2 into separate brackets. The divider/2
is calculated by the assembler first, addition of 1000000 follows.
Before dividing this sum by divider we'll have to insert the sum into
brackets.
If you do that, the following results:

List of symbols: Type nDef nUsed Decimalval Hexval Name C 1 2 1920 0780 DIVIDER C 1 0 521 0209 FREQUENCYNormally the calculation would have yielded a frequency of 520.8333 (period), therefore rounding the frequency up to 521 is correct.

What if those skipped digits behind the decimal dot are interesting? That would be the case if our timer uses a precscaler value of 1,024 and divides by 256. Then a rectangle of the output pin of

would result and the 0.907 behind the dot would be good to see.

If we simply calculate the 1000-fold, e. g.

```
.equ divider = 1024 * 256 * 2
.equ fmHz = (1000 * 1000000 + divider / 2) / divider
```

we will get the frequency in mHz instead of Hz.
List of symbols: Type nDef nUsed Decimalval Hexval Name C 1 2 524288 080000 DIVIDER C 1 0 1907 0773 FMHZThe 1907 now are the mHz, the three decimals behind the dot get visible. And: the last digit is rounded! Unfortunately the lack of assembler to handle small and large letters has made MHz from our mHz, but we could name the constant fmillihertz, so have a more correct name for the constant.

We use a 16-bit timer (that can divide by up to 65,536) and a prescaler of 1,024. Together this divides by 67,108,864, and is larger than any clock rate of an AVR can be. If we calculate the frequency we'll get an integer zero. If we calculate the cycle time from the frequency, e. g. in µs, we can do that with that formulation:

```
.equ divider = 65536 * 1024 * 2
.equ f=(1000000 + divider/2) / divider
.equ tus=(1000000 + f/2) / f
```

then we run into the following error message:
===> Error 101: Division by Zero Line: .equ tus=(1000000+f/2) / fbecause f is zero:

List of symbols: Type nDef nUsed Decimalval Hexval Name C 1 2 1342189568 50003000 DIVIDER C 1 2 0 00 F C 1 0 0 00 TUSBy looking into the symbol list, we'll find the reason for that error very fast.

Avoiding this is simple: just use a more correct dimension of numbers. So, if you want to express the duration of a clock cycle at 1 MHz, just change from

```
.equ clock = 1000000 ; Clock to 1 MHz
.equ clockduration = (1 + clock/2) / clock ; Duration, rounded
```

which will, of course, yield 0 for clockduration in integer math. To
avoid this, change to one of the following three formulations:
```
.equ clockduration_us = (1000000+clock/2) / clock ; clock duration in micro-seconds, rounded
.equ clockduration_ns = (1000000000+clock/2) / clock ; clock duration in nano-seconds, rounded
.equ clockduration_ps = (1000000000000+clock/2) / clock ; clock duration in pico-seconds, rounded
```

Having the dimension as part of the constant's name, makes clear enough
what the number represents. Even if you use such a variable in further
calculations, it is good to have the dimension as part of the name, because
you immediately see, which conversions factors you'll have to apply.
Don't be afraid, that your atto- and femto-seconds provoke an overflow: even only 32-bit integers can handle numbers up to 2 billions (2E9), so the pico-second example will end with an overflow error. The nowadays usual 64-bit integers in more modern assemblers (Assembler 2 in Studio 4.19) can handle numbers up to 9E+18, so even the atto- or femto-seconds are not a problem.

Newer assemblers use 64-bit numbers, and there are rarely any cases where you come near to the maximum and (negative) minimum of integers. So you can calculate your frequency in pico-Hertz, if you love to see useless digits hanging around in your symbol list.

To the page top

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