另一个装配问题!
使用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。有谁知道出了什么问题?真诚地感谢任何帮助!
答案 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
所以这只是一封小信。遗憾!