[ Pobierz całość w formacie PDF ]

Besides the manipulation of the bits in a register, copying a single bit is possible using the so-called T-bit
of the status register. With
BLD R1,0
the T-bit is loaded with a copy of bit 0 in register R1. The T-bit can be set or cleared, and its content can be
copied to any bit in any register:
CLT ; clear T-bit, or
SET ; set T-bit, or
BST R2,2 ; copy T-bit to register R2, bit 2
Shift and rotate
Shifting and rotating of binary numbers means multiplicating and dividing them by 2. Shifting has several
sub-instructions.
Multiplication with 2 is easily done by shifting all bits of a byte one binary digit left and writing a zero to the
least significant bit. This is called logical shift left. The former bit 7 of the byte will be shiftet out to the carry
bit in the status register.
LSL R1
The inverse division by 2 is the instruction called logical shift right.
LSR R1
The former bit 7, now shifted to bit 6, is filled with a 0, while the former bit 0 is shifted into the carry bit of
the status register. This carry bit could be used to round up and down (if set, add one to the result).
Example, division by four with rounding:
LSR R1 ; division by 2
BRCC Div2 ; Jump if no round up
INC R1 ; round up
Div2:
LSR R1 ; Once again division by 2
BRCC DivE ; Jump if no round up
INC R1 ; Round Up
DivE:
So, dividing is easy with binaries as long as you divide by multiples of 2.
If signed integers are used the logical shift right would overwrite the sign-bit in bit 7. The instruction
 arithmetic shift right ASR leaves bit 7 untouched and shifts the 7 lower bits, inserting a zero into bit
location 6.
Avr-Asm-Tutorial 28 http://www.avr-asm-tutorial.net
ASR R1
Like with logical shifting the former bit 0 goes to the carry bit in the status register.
What about multiplying a 16-bit word by 2? The most significant bit of the lower byte has to be shifted to
yield the lowest bit of the upper byte. In that step a shift would set the lowest bit to zero, but we need to
shift the carry bit from the previous shift of the lower byte into bit 0. This is called a rotate. During rotation
the carry bit in the status register is shifted to bit 0, the former bit 7 is shifted to the carry during rotation.
LSL R1 ; Logical Shift Left of the lower byte
ROL R2 ; ROtate Left of the upper byte
The logical shift left in the first instruction shifts bit 7 to carry, the ROL instruction rolls it to bit 0 of the
upper byte. Following the second instruction the carry bit has the former bit 7. The carry bit can be used to
either indicate an overflow (if 16-bit-calculation is performed) or to roll it into upper bytes (if more than 16
bit calculation is done).
Rolling to the right is also possible, dividing by 2 and shifting carry to bit 7 of the result:
LSR R2 ; Logical Shift Right, bit 0 to carry
ROR R1 ; ROtate Right and shift carry in bit 7
It's easy dividing with big numbers. You see that learning assembler is not THAT complicated.
The last instruction that shifts four bits in one step is very often used with packed BCDs. This instruction
shifts a whole nibble from the upper to the lower position and vice versa. In our example we need to shift
the upper nibble to the lower nibble position. Instead of using
ROR R1
ROR R1
ROR R1
ROR R1
we can perform that with a single
SWAP R1
This instruction exchanges the upper and lower nibble. Note that the upper nibble's content will be
different after applying these two methods.
Adding, subtracting and comparing
The following calculation operations are too complicated for the beginners and demonstrate that assembler
is only for extreme experts, hi. Read on your own risk!
To start complicated we add two 16-bit-numbers in R1:R2 and R3:R4. (In this notation, we mean that the
first register is the most signifant byte, the second the least significant).
ADD R2,R4 ; first add the two low-bytes
ADC R1,R3 ; then the two high-bytes
Instead of a second ADD we use ADC in the second instruction. That means add with carry, which is set or
cleared during the first instruction, depending from the result. Already scared enough by that complicated
math? If not: take this!
We subtract R3:R4 from R1:R2.
SUB R2,R4 ; first the low-byte
SBC R1,R3 ; then the high-byte
Again the same trick: during the second instruction we subract another 1 from the result if the result of the
first instruction had an overflow. Still breathing? If yes, handle the following!
Now we compare a 16-bit-word in R1:R2 with the one in R3:R4 to evaluate whether it is bigger than the
second one. Instead of SUB we use the compare instruction CP, instead of SBC we use CPC:
CP R2,R4 ; compare lower bytes
CPC R1,R3 ; compare upper bytes
If the carry flag is set now, R1:R2 is bigger than R3:R4.
Now we add some more complicated stuff. We compare the content of R16 with a constant: 0b10101010.
CPI R16,0xAA
If the Zero-bit in the status register is set after that, we know that R16 is 0xAA. If the carry-bit is set, we
know, it is smaller. If Carry is not set and the Zero-bit is not set either, we know it is bigger.
And now the most complicated test. We evaluate whether R1 is zero or negative:
TST R1
If the Z-bit is set, the register R1 is zero and we can follow with the instructions BREQ, BRNE, BRMI,
Avr-Asm-Tutorial 29 http://www.avr-asm-tutorial.net
BRPL, BRLO, BRSH, BRGE, BRLT, BRVC or BRVS to branch around a bit.
Still with us? If yes, here is some packed BCD calculations. Adding two packed BCDs can result in two
different overflows. The usual carry shows an overflow, if the higher of the two nibbles overflows to more
than 15 decimal. Another overflow, from the lower to the upper nibble occurs, if the two lower nibbles add
to more than 15 decimal.
To take an example we add the packed BCDs 49 (=hex 49) and 99 (=hex 99) to yield 148 (=hex 0x0148).
Adding these in binary math, results in a byte holding hex 0xE2, no byte overflow occurs. The lower of the
two nibbles should have an overflow, because 9+9=18 (more than 9) and the lower nibble can only handle
numbers up to 15. The overflow was added to bit 4, the lowest significant bit of the upper nibble. Which is
correct! But the lower nibble should be 8 and is only 2 (18 = 0b0001.0010). We should add 6 to that nibble
to yield a correct result. Which is quite logic, because whenever the lower nibble reaches more than 9 we
have to add 6 to correct that nibble.
The upper nibble is totally incorrect, because it is 0xE and should be 3 (with a 1 overflowing to the next
upper digit of the packed BCD). If we add 6 to this 0xE we get to 0x4 and the carry is set (=0x14). So the
trick is to first add these two numbers and then add 0x66 to correct the 2 digits of the packed BCD. But
halt: what if adding the first and the second number would not result in an overflow to the next nibble? And
not result in a digit above 9 in the lower nibble? Adding 0x66 would then result in a totally incorrect result.
The lower 6 should only be added if the lower nibble either overflows to the upper nibble or results in a [ Pobierz całość w formacie PDF ]
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • akte20.pev.pl