为什么PUSH的寄存器列表不能包含PC?

如何解决为什么PUSH的寄存器列表不能包含PC?

PUSH {R0,PC} ; A1477E: This register combination results in UNPREDICTABLE behaviour

为什么它会导致不可预测的行为?为什么在寄存器列表中允许 LR 而不允许 PC?我认为在堆栈中使用 LR 实现递归函数会容易得多,但是当我们仍然可以使用 PC 编写递归函数时,为什么它没有包含在有效的寄存器列表中?

解决方法

试试这些说明

PUSH {R0,R7}
PUSH {R0,R8}

然后拆解,你明白了吗:

0:  e92d0081    push    {r0,r7}
4:  e92d0101    push    {r0,r8}

或者这个:

0:  b481        push    {r0,r7}
2:  e92d 0101   stmdb   sp!,{r0,r8}

还是寄存器列表无效的错误(r8无效)?

如果您获得第一组,那么您是为 ARM 而不是拇指构建,并且警告/错误消息更有意义(对于 r15)。如果您正在构建拇指,它应该说无效(对于 r15 和/或 r8)。

早期的 ARM 文档(用于 ARM)

如果在存储的值中指定了 R15,则实现定义

现在他们说:

SP 和 PC 可以在 ARM 指令的列表中,但不能在 Thumb 指令中。但是:

• ARM 弃用在列表中包含 PC 的 ARM 指令

阅读更多(你现在应该已经阅读了)

str pc,[sp,#-4]!

0:  e52df004    push    {pc}        ; (str pc,#-4]!)

在 armv7-a 中也显示为已弃用,而较旧的实现定义为当时的一些附加注释:

读取程序计数器

当一条指令读取 R15 而不破坏其使用的任何限制时,读取的值是指令的地址加上 8 个字节。由于 ARM 指令始终是字对齐的,因此结果值的位 [1:0] 始终为零。 (在架构的 T 变体中,此行为在 Thumb 状态执行期间发生变化 - 有关详细信息,请参阅第 A6 章 Thumb 指令集。)这种读取 PC 的方式主要用于对附近指令和数据进行快速、位置无关的寻址,包括程序中与位置无关的分支。

当 STR 或 STM 指令存储 R15 时,会出现上述规则的一个例外。此类指令可以存储指令地址加 8 个字节,就像其他读取 R15 的指令一样,也可以存储指令自己的地址加 12 个字节。使用 8 的偏移量还是使用 12 的偏移量是 IMPLEMENTATION DEFINED 。对于存储 R15 的所有 STR 和 STM 指令,实现必须使用相同的偏移量。其中一些不能使用 8,而另一些不能使用 12。

由于这个异常,通常最好避免使用存储 R15 的 STR 和 STM 指令。如果这很困难,请在程序中使用合适的指令序列来确定实现使用的偏移量。

您应该已经注意到,在 ARMv7-M 中它也使用了 16 位寄存器掩码,但是 r15 和 r13 位置被标记为 (0)。

现在如果你进入并输入机器码 0xe92d8101 (thumb2) 你至少会看到 gnu 反汇编程序显示

0: e92d 8101 stmdb sp!,r8,pc}

但我必须挖出一个或几个 cortex-m3 才能看到它们的行为。

Keil 可能只是简单地采用了之前存在的 ARM 警告并将其应用于拇指编码(或回收警告而不是创建新警告),程序计数器的掩码中有一个位置,您不应该使用它和/或不应对其使用做出假设。而不是推送一些东西,使用你推送的其中一个东西来获取当时电脑的副本,然后推送它,这将是可预测的,无论你认为通过推送电脑提供什么价值,你都可以拥有。

,

您在 ARM(至少 ARMv7)中调用子例程的方式是使用 BLBLX 指令。 PUSH 直到子例程开始执行时才会发生,到那时 PC 中的地址指向一两个指令通过推送,而不是通过分支和关联。当您到达 PUSH 时,PC 不再具有从子例程返回的有用信息。

链接寄存器由处理器硬件加载,作为执行分支和链接的一部分,此时处理器确实知道正确的返回地址。

现在,当从子程序返回时,我们基本上希望将链接寄存器中的值返回到程序计数器中。有几种方法可以做到这一点。正如您所注意到的,您可以 PUSH {LR}POP {PC} 但除非您的子程序本身调用子程序,否则没有必要推送 LR。简单的函数可以只使用 BX LR。其他一些说明允许您将 PC 用作目标,但其中一些已被弃用。一个有趣的例子是 ARMv7-A 的特殊 return-from-exception:SUBS PC,LR,#4

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res