Reputation: 87
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
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
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