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

81、【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:压栈内容

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

背景

接之前 blog
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈指针和帧指针(上)
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈指针和帧指针(下)
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:r7 寄存器
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈空间对齐
分析了栈指针和帧指针的一些概念,演示了栈帧的操作,解释了为什么选择 r7 寄存器作为帧指针,并分析了栈空间对齐,下面最后再补充点压栈内容细节

压栈内容

之前 blog 【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈指针和帧指针(下) 分析了,参数寄存器只有 4 个,当输入参数超过 4 个时,需要将参数进行压栈
在这里插入图片描述
下面来看下参数超过 4 个的情况,代码如下

// main.c
static int add_func(int a, int b, int c, int d, int e) {return (a + b + c + d + e);
}int main(void) {int c = add_func(1, 2, 3, 4, 5);return 0;
}

终端 bash 中输入编译命令

arm-none-eabi-gcc -S -mcpu=cortex-m4 -mthumb main.c -o main.s

得到汇编文件 main.s

	.cpu cortex-m4.arch armv7e-m.fpu softvfp.eabi_attribute 20, 1.eabi_attribute 21, 1.eabi_attribute 23, 3.eabi_attribute 24, 1.eabi_attribute 25, 1.eabi_attribute 26, 1.eabi_attribute 30, 6.eabi_attribute 34, 1.eabi_attribute 18, 4.file	"main.c".text.align	1.syntax unified.thumb.thumb_func.type	add_func, %function
add_func:@ args = 4, pretend = 0, frame = 16@ frame_needed = 1, uses_anonymous_args = 0@ link register save eliminated.push	{r7}sub	sp, sp, #20add	r7, sp, #0str	r0, [r7, #12]str	r1, [r7, #8]str	r2, [r7, #4]str	r3, [r7]ldr	r2, [r7, #12]ldr	r3, [r7, #8]add	r2, r2, r3ldr	r3, [r7, #4]add	r2, r2, r3ldr	r3, [r7]add	r2, r2, r3ldr	r3, [r7, #24]add	r3, r3, r2mov	r0, r3adds	r7, r7, #20mov	sp, r7@ sp neededpop	{r7}bx	lr.size	add_func, .-add_func.align	1.global	main.syntax unified.thumb.thumb_func.type	main, %function
main:@ args = 0, pretend = 0, frame = 8@ frame_needed = 1, uses_anonymous_args = 0push	{r7, lr}sub	sp, sp, #16add	r7, sp, #8movs	r3, #5str	r3, [sp]movs	r3, #4movs	r2, #3movs	r1, #2movs	r0, #1bl	add_funcstr	r0, [r7, #4]movs	r3, #0mov	r0, r3adds	r7, r7, #8mov	sp, r7@ sp neededpop	{r7, pc}.size	main, .-main.ident	"GCC: (15:13.2.rel1-2) 13.2.1 20231009"

main

下面先来分析 main 函数
在这里插入图片描述

  • 56 行:将帧指针 r7 和返回地址 lr 进行压栈,保存好之前的上下文状态
    在这里插入图片描述
  • 57 行:sp 减去 16 字节,为 main 函数留出 16 字节的栈空间,注意,之前 add_func 只有 2 个输入参数的时候,sp 减去的是 8 字节,之所以这里多了 8 字节,是因为现在 add_func 有 5 个输入参数,其中 4 个参数由 R0-R3 参数寄存器保存,还剩下一个参数,需要保存到栈上
  • 这个多出来的参数是 int 类型,占 4 个字节,之前 blog 【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:栈空间对齐 提到过,函数入口处,栈空间需要 8 字节对齐,而这个参数不属于 main 的栈空间,和 main 里面那些局部变量不属于一个系统,不能和栈空间里面的局部变量进行合并,所以这里单独占了 8 字节的入参进栈空间(caller-saved 原则),加上原先栈空间已对齐的 8 字节空间,所以是 8 + 8 = 16 字节空间
    在这里插入图片描述
  • 58 行:将帧指针 r7 加上 8 字节,这 8 字节属于 main 入参进栈保存的空间,不属于局部变量所属的栈空间,r7 帧指针不能操作读取
  • 59-60 行: 将多出来的一个入参保存到栈上
  • 61-64 行:剩下 4 个参数分别保存到 R0-R3 参数寄存器上
  • 65 行:跳转到 add_func

add_func

下面来看 add_func
在这里插入图片描述

  • 24 行:将帧指针 r7 压入栈中,之前 blog 【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:叶子函数 有介绍过,为什么不把 lr 返回地址也压栈
    在这里插入图片描述

  • 25 行:为 add_func 申请 20 个字节的栈空间,用于存放局部变量,有 5 个 int 类型的入参,再加上前面压栈的 r7 寄存器,刚好 5 * 4 + 4 = 24 字节,已实现了 8 字节对齐
    在这里插入图片描述

  • 26 行:不需要额外申请 add_func 入参进栈空间,这里 sp 和 fp 相等

  • 27-30 行:将 R0-R3 参数寄存器的值保存到栈上空间

  • 31-37 行:将前 4 个入参进行相加

  • 38 行:将第 5 个入参从栈上取出,这里偏移 24 个字节,刚好到了 main 入参进栈的空间

  • 39-40 行:将第 5 个入参相加,结果保存到 R0 寄存器

至此,压栈内容分析完毕,后面继续开始栈溢出内容分析

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

相关文章:

  • MC0462最后一难
  • Redis进阶--集群
  • C study notes[1]
  • LVS技术知识详解(知识点+相关实验部署)
  • simulink系列之模型接口表生成及自动连线脚本
  • 消息队列:数字化通信的高效纽带
  • SQL Server和PostgreSQL填充因子
  • HCIA综合实验
  • string【下】- 内功修炼(搓底层)
  • C++入门--lesson4
  • CCF编程能力等级认证GESP—C++6级—20250628
  • ICT测试原理之--什么是假短
  • 基于opencv的人脸识别考勤系统
  • 人工智能与心理史学:从阿西莫夫的科幻预言到可计算社会模型>
  • Chris Fraser | 中国早期思想中墨家与荀子的知识论
  • 【完整代码】融合时序轨迹与49维特征反演的双色球开奖预测模型:一项关于隐藏规律的探索
  • Maven常用知识总结
  • Docker容器原理和启动策略
  • 传统浏览器过时了?Dia如何用AI重新定义上网体验
  • 零基础学习性能测试第二章-linux服务器监控:内存监控
  • 【60】MFC入门到精通——运行后 button按键上不显示 按键名, 控件上的文字不显示
  • 阶段1--Linux存储管理
  • Codeforces Round 1037(Div3)
  • 【web安全】万能密码
  • 车载诊断架构 --- OEM对于DTC相关参数得定义
  • 计算机网络1.1:计算机网络在信息时代的作用
  • 教你如何借助AI精读文献
  • python基础笔记
  • LRU算法及优化
  • 佛经个人阅读(一)《心经》解析