Assembly 解释字符串链表的AVR宏

Assembly 解释字符串链表的AVR宏,assembly,avr,atmega,Assembly,Avr,Atmega,嗨,我正在学习一个微处理器类,试图创建一个递归函数,返回链表结构中某些字符串的长度 我得到了这个宏,希望有人能帮助我理解它。我特别想知道如何使用这个宏创建一个链表 .set NEXT_STRING = 0x0000 .macro defstring .set T = PC .dw NEXT_STRING << 1 .set NEXT_STRING = T .if strlen(@0) & 1 .db @0, 0 .el

嗨,我正在学习一个微处理器类,试图创建一个递归函数,返回链表结构中某些字符串的长度

我得到了这个宏,希望有人能帮助我理解它。我特别想知道如何使用这个宏创建一个链表

.set NEXT_STRING = 0x0000
.macro defstring 
    .set T = PC 
    .dw NEXT_STRING << 1 
    .set NEXT_STRING = T 
    .if strlen(@0) & 1 
    .db @0, 0
    .else 
    .db @0, 0, 0
    .endif    
.endmacro
。设置下一个\u字符串=0x0000
.宏定义字符串
.set T=PC

.dw NEXT_STRING下面的行声明了一个名为
NEXT_STRING
的汇编器常量,其值为0。只要程序中出现
下一个\u字符串
,它就会被
0
替换

.set NEXT_STRING = 0x0000
我认为下一个字符串的名称可能会令人困惑。它实际上是指向在程序集文件中声明的最后一个字符串的指针

此行将
T
设置为等于当前程序计数器(PC)。这就是汇编程序正在写入的闪存中的当前位置

.set T = PC 
下面的
.dw
指令使用指定值将16位字写入闪存。这个单词将存储指向列表中下一个节点的指针,因此我们将其设置为
next\u STRING
。位移位部分可能是由于PC以字为单位计数,而AVR指针以字节为单位计数,因此在将PC值转换为指针时,必须乘以2。这是代码的第一部分,它实际上向flash编写了任何东西

.dw NEXT_STRING << 1
在这一点上,我想你可以看到一个链表正在形成。第一次调用
defstring
时,一个空指针存储在flash中,有一天它将成为链表的结尾。然后再次调用它,它会生成第二个指针,指向第一个指针。然后再次调用它,它会生成第三个指针,指向第二个指针

链表只有在其中包含一些数据时才有用,因此宏要做的下一件事是使用下面的代码添加字符串数据。写这篇文章的人决定总是以空字节结束字符串(这是C语言字符串的标准),并且如果字符串的长度为奇数,他们还决定添加额外的填充字节,以确保链表中节点占用的空间始终为偶数。这称为2-对齐,它可能使AVR更容易加载2字节指针。我不认为这种对齐是必要的,但如果有必要,我更愿意在宏的开头和/或结尾使用
.align 2
指令,而不是这样做

.if strlen(@0) & 1 
.db @0, 0
.else 
.db @0, 0, 0
.endif
旁白:这不是在AVR中存储字符串列表的唯一方法。您在C程序中看到的一种更标准的方法是将所有字符串放在一个位置,然后在另一个位置放一个指针数组。数组的长度可以是常量,也可以由空指针终止数组。Windows注册表中的REG_MULTI_SZ data使用的另一个选项是只将字符串一个接一个地存储在内存中,不使用指针,以空字节分隔,以两个空字节结束。每个方法都提供不同的空间/性能权衡,最后一个方法不能存储空字符串

.if strlen(@0) & 1 
.db @0, 0
.else 
.db @0, 0, 0
.endif