stealthbomber10
stealthbomber10

Reputation: 87

How do I compute the 16-bit dot product of two arrays containing 8-bit values?

Another assembly question!

Using an Arduino, I have to write a function in Atmel AVR Assembly for my computer science class that calculates the dot product of two arrays and returns it as a 16-bit integer. The arrays are of equal length and each contains a set of 8-bit values. The function is supposed to take in those two byte-arrays and a byte representing the length of the array as arguments. I am allowed to use branching instructions and such.

Here is what I have so far:

.global dot
dot:
  mov r18,r22
  mov r19,r23
  movw r26,r18
  mov r30,r24
  mov r31,r25
  ldi r18,lo8(0)
  ldi r19,hi8(0)
  jmp exit_if
  compute:
    ld r25,Z+
    ld r22,X+
    muls r22,r25
    movw r22,r0
    clr r1
    add r18,r22
    adc r19,r23
  exit_if:
    mov r25,r30
    sub r25,r24
    cp r25,r20
    brlt compute
    movw r24,r18
    ret

It's a bit of a monstrosity I know...

For some reason when I have the arrays byte a[] = {7, 20, 19, 11, 4} and byte b[] = {132, 51, 0, 84, 30}, with the length argument equal to 5 (obviously), it does not return 2988 like it is supposed to. Does anyone know what is going wrong? Any help would be sincerely appreciated!

Upvotes: 0

Views: 758

Answers (2)

stealthbomber10
stealthbomber10

Reputation: 87

I figured it out everyone.

For the line

muls r22, r25

I should have made it

mul r22, r25

So it was just one little letter. Sorry!

Upvotes: 0

Yann Vernier
Yann Vernier

Reputation: 15887

Tried to translate your code to a slightly higher abstraction level.

.global dot
dot:
  mov r18,r22
  mov r19,r23
/* r18r19 = r22r23; */
  movw r26,r18
/* X = r26r27 = r18r19; */
  mov r30,r24
  mov r31,r25
/* Z = r30r31 = r24r25; */
  ldi r18,lo8(0)
  ldi r19,hi8(0)
/* r18r19 = 0; */
/* jmp - innerlabel - testlabel pattern: while() loop */
  jmp exit_if
  compute:
    ld r25,Z+         // r25 = *(Z++)
    ld r22,X+         // r22 = *(X++)
    muls r22,r25      // multiplies vector elements, result in r0:r1
    movw r22,r0       // r22r23 = a[i]*b[i], signed
    clr r1            // r1=0
    add r18,r22
    adc r19,r23       // r18r19 += r22r23
  exit_if:
    mov r25,r30     // r25 = r30;
    sub r25,r24     // r25 -= r24;  8-bit count of how many bytes have been read
    cp r25,r20      // compare to r20
    brlt compute    // if r25<r20 loop
    movw r24,r18    // r24r25 = r18r19
    ret

Found register meanings at entry: r20 is vector length. r24r25 is one vector location. r22r23 is the other vector location. For some inexplicable reason r18r19, which is used to track the sum in the loop, temporarily holds a copy of one of the pointers. Result is eventually placed in r24:r25.

This could reasonably perform the task, it seems. So the next question is indeed what the ABI and arguments really are.

Upvotes: 1

Related Questions