关于 GNU ARM 汇编程序的意外警告

Posted

技术标签:

【中文标题】关于 GNU ARM 汇编程序的意外警告【英文标题】:Unexpected warning on GNU ARM Assembler 【发布时间】:2013-02-28 17:12:43 【问题描述】:

我正在为 Raspberry Pi 编写一些裸机代码,并且收到来自 Windows 上的 ARM 交叉汇编程序的意外警告。导致警告的说明是:

stmdb sp!,r0-r14^

ldmia sp!,r0-r14^

警告是:

警告:基址寄存器的写回不可预测

我可以这样理解,虽然 '^' 修饰符告诉处理器存储寄存器的用户模式副本,但它不知道当指令执行时处理器将处于什么模式并且没有' t 似乎是一种告诉它的方式。我有点担心收到相同的警告:

stmdb sp!,r0-r9,sl,fp,ip,lr^

和:

ldmia sp!,r0-r9,sl,fp,ip,lr^

尽管我明确不存储 ANY sp 寄存器。

我担心的是,尽管大约 15 年前我曾经做过很多汇编代码,但 ARM 代码对我来说是新的,我可能会误解一些东西!另外,如果我可以安全地忽略这些警告,有没有办法抑制它们?

【问题讨论】:

【参考方案1】:

术语“写回”不是SP 在寄存器列表中的存在或不存在,而是指! 符号,这意味着该指令应该更新SP值与传输区地址结束。基址寄存器 (SP) 值将用于当前模式,而不是用户模式,因此您仍然可以将用户模式 ​​SP 值加载或存储到堆栈中。来自 ARM ARM B9.3.6 LDM(用户寄存器):

在系统模式以外的 PL1 模式下,加载多个(用户寄存器) 从连续的内存位置加载多个用户模式寄存器 使用来自基址寄存器的地址。加载的寄存器不能 包括电脑。处理器正常读取基址寄存器值, 使用当前模式来确定正确的 Banked 版本 登记。该指令不能写回基址寄存器。

编码图通过将第 21 位(W,写回)指定为“(0)”来反映这一点,这意味着如果该位不为 0,则结​​果是不可预测的。

所以解决方案就是不指定!,必要时手动递减或递增SP。

【讨论】:

啊,我错过了架构参考手册中的那一点,尽管我必须承认我一直在使用 ARM1176JZF-S 技术参考手册来获取我的大部分信息,但这似乎并不适用这么详细!我使用 Google 发现的警告的所有解释(不是很多!)都说警告是因为您正在写回正在加载/存储的寄存器。我理解写回是指基址寄存器的更新。【参考方案2】:

ARM 架构参考手册说在用户寄存器的 LDM/SMT 中不允许写回。它在异常返回情况下是允许的,其中pc 在寄存器列表中。

LDM(异常返回)

LDM<amode><c> <Rn>!,<registers_with_pc>^

LDM(用户注册)

LDM<amode><c> <Rn>,<registers_without_pc>^

【讨论】:

所以,要使用第一种形式从异常中返回,您必须在不回写的情况下存储寄存器,更新堆栈指针,然后您可以使用带有回写的版本返回!这个限制似乎有点奇怪,但我相信这是有原因的。至少在加载 pc 时允许 writeback,否则就没用了!

以上是关于关于 GNU ARM 汇编程序的意外警告的主要内容,如果未能解决你的问题,请参考以下文章

博文连载ARM编译器ARM汇编与ARM GNU汇编

GNU ARM汇编快速入门

GNU ARM 汇编指令

GNU ARM汇编语法

由于在 IAR 工作台中使用 GNU ARM 工具链而导致的错误

GNU ARM 汇编基础笔记