当前位置: 首页 > news >正文

79、【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:r7 寄存器

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

接之前 blog
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈指针和帧指针(上)
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈指针和帧指针(下)
分析了栈指针和帧指针的一些概念,并演示了栈帧的操作,在 blog 最后留了个疑问,AAPCS32 文档里写了 r11 作为帧指针寄存器,怎么代码里却用的是 r7?下面来补充解释下这里面栈帧的一些细节

帧指针的选择

之前分析到 AAPCS 这里,可以看到 r11 为帧指针寄存器
在这里插入图片描述
而不是在汇编文件里面看到的 r7 作为帧指针寄存器
在这里插入图片描述
其实有两个细节:

  • 文档里面有描述,r11 可以被用作一个帧指针,首先是英文里 may 的表达,这里用了 may 而不是 must,may 表示可能性或可以,语气委婉,而 must 强调必要性或确定性,语气更加强烈,从单词的使用用法来说,通常情况下,r11 是推荐使用作为帧指针的,而不是强制要求使用
    在这里插入图片描述
  • 其次,我们翻阅的这篇文档是 AAPCS32,意味着它是基于 arm32 位指令集的,而stm32f429i 系列是基于 Arm Cortex-m4 核,是基于 thumb 指令集的
    arm32 和 thumb 是 arm 架构中两种不同的指令集状态,在帧指针这块的使用上,有所区别,那么有没有 AAPCS_Thumb 的专门文档呢?没有,AAPCS 在架构上只区分 32 位和 64 位,thumb(这里一般指 thumb2,16 位和 32 位指令混合使用)可以用 AAPCS32 规范来 cover 住
    在这里插入图片描述

gcc 源码注释

关于帧指针的选择,在 gcc 源码中可以找到蛛丝马迹,gcc 源码链接如下
https://github.com/gcc-mirror/gcc

在 arm.cc 文件中,有这么一段注释
在这里插入图片描述

  • 这里划红线的说明,在 thumb 模式下,如果需要帧指针,则使用 r7 寄存器

  • 而 r11 是 32 位 arm 模式下的传统帧指针寄存器

  • 这里有两个概念,hard frame pointer 和 soft frame pointer

  • hard frame pointer 是一种传统意义上的帧指针,是一个特定的寄存器,比如 arm32 中的 r11,在调用约定里面明确规定了
    在这里插入图片描述

  • soft frame pointer 是一种更加灵活的帧指针实现方式,在需要时启用,不像 hard frame pointer 那样固定为某个寄存器,而是根据编译器的优化策略决定使用哪个寄存器,比如 gcc 上选择的是 r7

为什么是 r7?

了解到 thumb 模式和 arm32 模式之后,再回到这个问题,为什么 thumb 选择了 r7,为什么 thumb 不能和 arm32 一样,选择 r11?

回答这个问题,再看下 Arm Cortex-M4 Processor Technical Reference Manual 这张图
在这里插入图片描述

  • 首先,R0-R7 寄存器可以接受所有指令,包括 16 位和 32 位的指令集,而 R8-R12 能接受 32 位指令,但只能接受部分 16 位指令集
  • 而 thumb 指令集是一个 16位 宽的指令集,相比 32 位宽的 ARM 指令集,在操作范围和灵活性上有所限制,对高寄存器(R8-R15)的操作受到更多限制,不能像处理低寄存器(R0-R7)那样直接访问
  • 所以 R8-R15 被排除,选择一个低寄存器(R0-R7)作为帧指针更符合 thumb 指令集的设计初衷
  • 而在 R0-R7 中,R0-R3 是 caller-saved,被排除
  • 而在 R4-R7 中,R4-R6 在实际编程实践中,更经常被用来存储局部变量或临时值,相比之下,R7 的使用频率较低,便顺理成章的成为了 soft frame pointer 的首选

-marm

最后,在 bash 终端输入如下命令

arm-none-eabi-gcc -S -marm main.c -o main.s

可以看到在 32 位指令集下,帧指针为默认的 fp(r11)寄存器
在这里插入图片描述
今天先到这儿,下篇 blog 继续

http://www.dtcms.com/a/284287.html

相关文章:

  • Modbus
  • PyCharm2024安装包社区版和专业版
  • TESOLLO五指灵巧手遥操作解决方案
  • 使用 .NET Core 的原始 WebSocket
  • Spring整合MyBatis详解
  • 概率论与数理统计(四)
  • WCDB soci 查询语句
  • 缓存雪崩、缓存穿透,缓存击穿
  • 使用IntelliJ IDEA和Maven搭建SpringBoot集成Fastjson项目
  • 【git】使用教程
  • CommonJS和ES模块区别对比
  • API开发提速新方案:SmartBear API Hub与ReadyAPI虚拟化整合实践
  • ESP8266服务器建立TCP连接失败AT+CIPSTART=“TCP“,“192.168.124.1“,8080 ERROR CLOSED
  • JAVA后端开发——success(data) vs toAjax(rows): 何时用
  • 美拍sig逆向
  • 神经网络:模拟人脑的 AI 信息处理系统
  • 代码随想录打卡第十二天
  • Unity | AmplifyShaderEditor插件基础(第十集:噪声的种类+火焰制作-下)
  • 透过结构看时间——若思考清洗则表达有力
  • 开源Agent平台Dify源码剖析系列(六)核心模块core/agent之CotCompletionAgentRunner
  • Web开发 01
  • Vue.js 的 Composition API 深度解析:构建高效可维护的前端逻辑
  • 让大模型输出更加规范化——指定插件
  • LVS部署DR模式集群
  • @Linux搭建DNS-主从服务器
  • Spring原理揭秘--Spring的AOP
  • cuda编程笔记(8)--线程束warp
  • Cookie 与 Session概述
  • AI编程实战:如何让AI生成带参数和返回值的Python函数——以PDF文本提取为例
  • 【橘子分布式】gRPC(理论篇)