AVR程序集:写入数组而不返回任何内容

时间:2019-04-26 03:24:03

标签: arrays assembly ld avr cpu-registers

我必须在AVR程序集中编写一个程序,该程序在被C程序调用时使用一个指向整数数组的指针,并对其元素执行操作,而无需实际输出值。为简单起见,假设我希望我的程序将每个元素的值加倍-这样,给定数组{2, 4, 6, 8},在C中调用与我编写的代码分开的print方法将打印{4, 8, 12, 16}

我的问题是我不明白如何更改数组元素的值,并且在函数完成执行后使这些更改仍然存在。我无法通过寄存器r24返回任何内容,因为我出于不同的目的需要返回不同的数字。

我的想法是,由于寄存器r24上的输入作为指向数组第一个元素的指针进入,因此我会mov r26 r24将数组与X指针关联(?),然后然后ld到另一个寄存器,以便我可以使用X指针在数组中递增,就像ld r18, X+一样。

尽管我在浏览数组时没有遇到什么麻烦,但我不理解如何赋予更改永久性(如果这样的话)。我的印象是希望使用st和/或sts来解决此问题,但是我一直在努力了解它们的工作原理。我的尝试是保留一个像Z这样的指针与输入数组关联,并且每当我有一个值准备替换数组中的旧元素时,我就写st Z+, rXX,将值放在索引Z上,然后随后指向下一个索引。这没有用,所以我不禁要问:如何将本地寄存器的内存与程序提供的输入的内存链接起来?

1 个答案:

答案 0 :(得分:2)

首先,我鼓励您阅读Application Note AT1886: Mixing Assembly and C with AVRGCC(pdf文档) 它描述了如何在调用例程之间传递参数和返回值。

要使汇编代码可从C调用,您必须为汇编函数编写一个声明存根。您可以将其放在.h文件中。使其成为具有一个指针类型参数且没有返回值的函数。

extern void my_function(void *); 

关键字extern将告诉链接器函数主体在其他位置,而不是在此.c文件中

现在,您可以添加程序集文件,在项目中创建新的.s文件。您可以在上面放上

#define _SFR_ASM_COMPAT 1
#define __SFR_OFFSET 0

#include <avr/io.h>

这些声明将使您能够使用指令in / out / cbi / sbi等访问较低的IO寄存器。

现在,您应该声明一个与函数名称相同的标签,并声明为.extern

 .extern my_function

 my_function:
   // assembly for the function body is here

如应用笔记中所述,第一个参数位于r25:r24中(第二个参数(如果有的话)位于r23:r22中,第三个位于r21:r20中,第四个位于r19:r18中)。如果您甚至有一个1字节的参数,则将全部使用两个寄存器,r24将存储其值,而r25则将不使用。第二个参数将在r23:r22等中。 如果您有4字节的值(例如long int),则它将使用两个相应的参数位置,即,该值将存储在r23:r22:r25:r24

如果您的代码使用寄存器r2-r17以及r28或r29(Y寄存器),则应保留并恢复其先前的值,然后再返回。另外,建议保留r0(请参阅应用笔记中的表5-1,但要考虑到打印不正确:r0位于r31上方第二行的底端,应读为r30)< / p>

寄存器r1始终包含0,如果您以某种方式更改了它的值(例如,调用MUL指令),则必须在返回之前将其清除。

因此,考虑我们的示例,假设您有一些C代码,该代码会调用汇编程序:

uint8_t my_array[10]; // declare an array

my_function(&my_array); // call the routine, passing pointer to the array

然后将调用您的函数,并且第一个参数(寄存器r25:r24)将包含指向该数组的指针。因此,您的汇编代码可以将其带入任何指针寄存器,并随心所欲。例如

 .extern my_function

 my_function:
   movw X, r24 // copy r25:r24 into X (r27:r26)
   ldi r18, 10
   st X+, r18 // store 10 into first element of the array
   ldi r18, 20
   st X+, r18 // store 20 into second element of the array
   ... etc

 ret // return

现在,如上例所示调用函数时,my_array[0]将包含10,my_array[1] == 20,等等。