为字符串链表解释这个 AVR 宏
Explain this AVR macro for linked list of strings
您好,我正在使用微处理器 class 并尝试创建一个递归函数,该函数 returns 链表结构中某些字符串的长度。
我得到了这个宏可以使用,希望有人能帮助我理解它。特别是我想知道如何使用这个宏创建链表。
.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
使用方法如下:
defstring "somestring"
defstring "another"
然后假设创建了一个链表,这些字符串作为数据保存在每个节点上。
感谢任何帮助,谢谢!
下面的行声明了一个名为NEXT_STRING
的汇编程序常量,其值为0。程序中任何出现NEXT_STRING
的地方,都会被0
替换。
.set NEXT_STRING = 0x0000
我认为 NEXT_STRING
这个名字可能会造成混淆。它实际上是指向您在程序集文件中声明的 last 字符串的指针。
此行将 T
设置为等于当前程序计数器 (PC)。这就是汇编程序正在写入的闪存中的当前位置。
.set T = PC
下面的 .dw
指令将一个 16 位字写入闪存,并具有指定的值。这个词将存储指向列表中下一个节点的指针,所以我们将它设置为等于NEXT_STRING
。位移部分可能是由于PC以字为单位计算,而AVR指针以字节为单位计算,因此在将PC值转换为指针时必须乘以2。这是实际向闪存写入任何内容的代码的第一部分。
.dw NEXT_STRING << 1
你生成的第一个指针将是一个空指针,因为NEXT_STRING
是0。但是我们设置NEXT_STRING
等于T
,这样当你调用下一个宏时时,指针会指向flash中最后一个指针存放的地方。
.set NEXT_STRING = T
至此,我想你可以看到正在形成一个链表。第一次调用 defstring
时,flash 中存储了一个空指针,有一天它会成为链表的末尾。然后你再次调用它,它会生成指向第一个的第二个指针。然后你再次调用它,它会生成指向第二个的第三个指针。
链接列表只有在其中有一些数据时才有用,因此宏接下来要做的是使用下面的代码添加字符串数据。写这篇文章的人决定他们希望始终以空字节结束字符串(这是 C 语言字符串的标准),并且他们还决定在字符串的长度为奇数时添加额外的填充字节,以确保 space 链表中某个节点所取的总是偶数。这称为 2-alignment 并且它可能使 AVR 更容易加载 2 字节指针。我不相信这种对齐是必要的,但如果是这样,我宁愿在宏的开头 and/or 末尾使用 .align 2
指令,而不是执行此 hack。
.if strlen(@0) & 1
.db @0, 0
.else
.db @0, 0, 0
.endif
旁白:这不是在 AVR 中存储字符串列表的唯一方法。您在 C 程序中看到的一种更标准的方法是将所有字符串放在一个地方,然后在另一个地方放一个指针数组。数组的长度要么是常量,要么数组可以由空指针终止。 Windows 注册表中的 REG_MULTI_SZ 数据使用的另一种选择是将字符串一个接一个地存储在内存中,没有指针,由空字节分隔,并以两个空字节结束。每种方法都为您提供了不同的 space/performance 权衡,最后一种方法不能存储空字符串。
您好,我正在使用微处理器 class 并尝试创建一个递归函数,该函数 returns 链表结构中某些字符串的长度。
我得到了这个宏可以使用,希望有人能帮助我理解它。特别是我想知道如何使用这个宏创建链表。
.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
使用方法如下:
defstring "somestring"
defstring "another"
然后假设创建了一个链表,这些字符串作为数据保存在每个节点上。
感谢任何帮助,谢谢!
下面的行声明了一个名为NEXT_STRING
的汇编程序常量,其值为0。程序中任何出现NEXT_STRING
的地方,都会被0
替换。
.set NEXT_STRING = 0x0000
我认为 NEXT_STRING
这个名字可能会造成混淆。它实际上是指向您在程序集文件中声明的 last 字符串的指针。
此行将 T
设置为等于当前程序计数器 (PC)。这就是汇编程序正在写入的闪存中的当前位置。
.set T = PC
下面的 .dw
指令将一个 16 位字写入闪存,并具有指定的值。这个词将存储指向列表中下一个节点的指针,所以我们将它设置为等于NEXT_STRING
。位移部分可能是由于PC以字为单位计算,而AVR指针以字节为单位计算,因此在将PC值转换为指针时必须乘以2。这是实际向闪存写入任何内容的代码的第一部分。
.dw NEXT_STRING << 1
你生成的第一个指针将是一个空指针,因为NEXT_STRING
是0。但是我们设置NEXT_STRING
等于T
,这样当你调用下一个宏时时,指针会指向flash中最后一个指针存放的地方。
.set NEXT_STRING = T
至此,我想你可以看到正在形成一个链表。第一次调用 defstring
时,flash 中存储了一个空指针,有一天它会成为链表的末尾。然后你再次调用它,它会生成指向第一个的第二个指针。然后你再次调用它,它会生成指向第二个的第三个指针。
链接列表只有在其中有一些数据时才有用,因此宏接下来要做的是使用下面的代码添加字符串数据。写这篇文章的人决定他们希望始终以空字节结束字符串(这是 C 语言字符串的标准),并且他们还决定在字符串的长度为奇数时添加额外的填充字节,以确保 space 链表中某个节点所取的总是偶数。这称为 2-alignment 并且它可能使 AVR 更容易加载 2 字节指针。我不相信这种对齐是必要的,但如果是这样,我宁愿在宏的开头 and/or 末尾使用 .align 2
指令,而不是执行此 hack。
.if strlen(@0) & 1
.db @0, 0
.else
.db @0, 0, 0
.endif
旁白:这不是在 AVR 中存储字符串列表的唯一方法。您在 C 程序中看到的一种更标准的方法是将所有字符串放在一个地方,然后在另一个地方放一个指针数组。数组的长度要么是常量,要么数组可以由空指针终止。 Windows 注册表中的 REG_MULTI_SZ 数据使用的另一种选择是将字符串一个接一个地存储在内存中,没有指针,由空字节分隔,并以两个空字节结束。每种方法都为您提供了不同的 space/performance 权衡,最后一种方法不能存储空字符串。