stealthbomber10
stealthbomber10

Reputation: 87

How do I compute the 8-bit average of two 8-bit values in assembly?

Using an Arduino, I have to write a function in Atmel AVR Assembly for my computer science class that computes the 8-bit average of two 8-bit values in assembly. I am not allowed to use any branching instructions either (but skips are fine).

This is what I have so far:

.global average
average:
  add r24, r22
  asr r24
  ret

For the part of my program where I have to compute the average of 69 and 60, it returns -64 instead of 64. Does anyone know how I would make this function work? Any help would be much appreciated.

Upvotes: 2

Views: 1499

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 365267

The trick is to add and then rotate-with-carry to divide the 9-bit result by 2 and leave an 8-bit result in a register.

Two of the answers on the question I linked in comments use that: first, second.

An AVR implementation of that is:

    add   r24, r25       ; 9-bit result in C and r24
    ror   r24            ; rotate-through-carry, like x86's RCR instruction

This works for signed or unsigned interpretation of the bits, since all we're doing is discarding the low bit from the 9-bit full result of the addition. There's no arithmetic vs. logical shift choice, and no wraparound.

Also note that division by shifting rounds towards -infinity (not truncating towards zero like C's integer division operator). So (1 + -2) >> 1 is -1.


This is small enough that you should put it in a macro, not a function. It probably takes at least 2 instructions at most call sites, so inlining this saves code size even if you could have used the 1-word RCALL instruction instead of 2-word CALL.

Upvotes: 10

Related Questions