如何计算包含8位值的两个数组的16位点积?

时间:2016-12-07 11:08:48

标签: arrays assembly arduino average avr

另一个装配问题!

使用Arduino,我必须在Atmel AVR Assembly中为我的计算机科学类编写一个函数,它计算两个数组的点积并将其作为16位整数返回。数组长度相等,每个数组包含一组8位值。该函数应该将这两个字节数组和一个表示数组长度的字节作为参数。我被允许使用分支指令等。

这是我到目前为止所做的:

.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

我知道这有点怪异......

出于某种原因,当我有数组字节a [] = {7,20,19,14,4}和字节b [] = {132,51,0,84,30}时,长度参数相等到5(显然),它不会像它应该的那样返回2988。有谁知道出了什么问题?真诚地感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

尝试将您的代码转换为略高的抽象级别。

.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

在条目处找到寄存器含义:r20是向量长度。 r24r25是一个矢量位置。 r22r23是另一个矢量位置。由于一些莫名其妙的原因r18r19(用于跟踪循环中的和),暂时保存其中一个指针的副本。结果最终放在r24:r25中。

这似乎可以合理地执行任务。所以下一个问题确实是ABI和论证的真正含义。

答案 1 :(得分:0)

我把它想出来了。

对于

muls r22, r25

我应该做到了

mul r22, r25

所以这只是一封小信。遗憾!