首页 > 解决方案 > 为什么在 AVR ASM 上使用 Z 寄存器访问程序存储器时要乘以 2

问题描述

我知道这个问题存在并且已经得到回答,但是当我得到答案时,我只是不明白为什么这个答案回答了这个问题。

在 AVR ASM 微控制器上,当我使用 Z 指针访问程序存储器时,为什么必须将加载到 ZH/ZL 寄存器上的地址乘以 2?

这是示例代码:

ldi ZL, low(2*label)
ldi ZH, high(2*label)

label:
.db "Hello world", 0
lpm

这是我目前在互联网上所做的研究所知道的(来源太有限了):

所以乘以 2 显然可以解决问题,但我不明白为什么。改写我可以说的问题:

虽然我需要从内存中加载数据0x4322,但我说 Z 指针从内存地址加载数据,0x8644因为那是字节地址。集会的人怎么知道?

附带问题:

我见过这种实现:

ldi ZL, low(label)
ldi ZH, high(label)

lsl ZL
rol ZH
label:
.db "Hello world", 0
lpm

如果标号程序存储器地址是0b10110011 11000000,执行lslandrol命令将产生一个0b01100110 10000000带有 C 标志设置 ( C=1) 的“字节”存储器。鉴于这里有两个溢出,它如何指向所需的程序内存字节?

标签: assemblymemoryavr

解决方案


虽然我需要从内存中加载数据0x4322,但我说 Z 指针从内存地址加载数据,0x8644因为那是字节地址。

这是关于常量的隐含单位:0x4322 个字是 0x8644 个字节(AVR 上的一个字节是 8 位,一个被定义为 16 位)。

汇编程序是怎么知道的?

可以从 AVR 使用手册中得出LPM Z使用字节地址的结论。Z哪些单位用于标签取决于您使用的汇编器(汇编器作为咀嚼汇编代码的工具)。因此,“汇编器确实知道”,因为它隐含在其开发人员实现的汇编器中:AVR 硬件不知道标签。

此外,还有不止一个 AVR 汇编器:GNU 汇编器使用以字节为单位的标签。


推荐阅读