assembly - 为什么在 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
这是我目前在互联网上所做的研究所知道的(来源太有限了):
- 程序存储器是字寻址的,而寄存器是字节寻址的:我从这句话中了解到,程序存储器 (
16 bit
) 中的地址包括2 bytes
AVR 上的寄存器8-bit
。因此,为了将数据加载到寄存器,您需要选择要从内存地址加载的两个字节中的哪一个。 - Z 指针的
LSB
选择将加载哪个字节:这意味着只有15-bits
您(在 Z 指针中)指定您将从其加载数据的程序存储器地址。
所以乘以 2 显然可以解决问题,但我不明白为什么。改写我可以说的问题:
虽然我需要从内存中加载数据0x4322
,但我说 Z 指针从内存地址加载数据,0x8644
因为那是字节地址。集会的人怎么知道?
附带问题:
我见过这种实现:
ldi ZL, low(label)
ldi ZH, high(label)
lsl ZL
rol ZH
label:
.db "Hello world", 0
lpm
如果标号程序存储器地址是0b10110011 11000000
,执行lsl
androl
命令将产生一个0b01100110 10000000
带有 C 标志设置 ( C=1
) 的“字节”存储器。鉴于这里有两个溢出,它如何指向所需的程序内存字节?
解决方案
虽然我需要从内存中加载数据
0x4322
,但我说 Z 指针从内存地址加载数据,0x8644
因为那是字节地址。
这是关于常量的隐含单位:0x4322 个字是 0x8644 个字节(AVR 上的一个字节是 8 位,一个字被定义为 16 位)。
汇编程序是怎么知道的?
可以从 AVR 使用手册中得出LPM Z
使用字节地址的结论。Z
哪些单位用于标签取决于您使用的汇编器(汇编器作为咀嚼汇编代码的工具)。因此,“汇编器确实知道”,因为它隐含在其开发人员实现的汇编器中:AVR 硬件不知道标签。
此外,还有不止一个 AVR 汇编器:GNU 汇编器使用以字节为单位的标签。
推荐阅读
- c# - 在其他应用程序中捕获按钮单击事件
- javascript - 基于列表鼠标悬停突出显示表格数据
- google-sheets - 如何从谷歌表格访问剪贴板?
- coffeescript - 如何向 coffescript HTTP-Listener (hubot) 添加身份验证
- java - 实体更改时休眠,数据库立即更改
- c++ - 是否可以通过模板指定抽象类变量类型?
- scrapy - scrapy如何完成cookie通信
- elasticsearch - 每个索引的 Elasticsearch 最大文档数
- c# - 为什么我已经在 Datagrid 中设置了 Columnheader?
- php - Laravel $touch 用于更新 updated_at