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

免费一键生成个人网站自己创建网站怎么赚钱

免费一键生成个人网站,自己创建网站怎么赚钱,网站开发过程中遇到的问题及解决办法,关键词简谱【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除 背景 接之前 blog 【OS】【Nuttx】【启动】ca…

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

背景

接之前 blog
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例
【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:叶子函数
分析了示例中体现的 caller-saved 和 callee-saved 规则,以及里面的叶子函数概念,下面来看下栈空间操作的一些具体细节

栈空间操作

还是回到之前那个示例

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

汇编代码如下

	.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 = 0, pretend = 0, frame = 8@ frame_needed = 1, uses_anonymous_args = 0@ link register save eliminated.push	{r7}sub	sp, sp, #12add	r7, sp, #0str	r0, [r7, #4]str	r1, [r7]ldr	r2, [r7, #4]ldr	r3, [r7]add	r3, r3, r2mov	r0, r3adds	r7, r7, #12mov	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, #8add	r7, sp, #0movs	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 函数这里的栈空间行为
在这里插入图片描述

LR 寄存器压栈

这个之前 blog 【OS】【Nuttx】【启动】caller-saved 和 callee-saved 示例:叶子函数 应该说得很详细了,因为调用了子函数,执行了跳转命令

...
bl add_func
str	r0, [r7, #4]
...
  • 这个指令会把返回地址(即 bl 下一条指令的地址,也就是 str r0, [r7, #4] 命令)写入 lr
  • 如果不保存原来的 lr 值,那么之前在 lr 中保存的内容就会被覆盖。
  • 为了能正确地从 main 返回到它的调用者(比如启动代码 _start 或操作系统),必须先把 lr 压栈保存

栈指针和帧指针

栈指针(Stack Pointer)和帧指针FP(Frame Pointer)是栈空间操作中两个非常重要的概念,它们各自承担不同的角色,

栈指针 SP

栈好理解,就是一个后进先出的数据结构,栈空间可以用来存储函数参数、返回地址、局部变量以及临时数据等,下面来看下官方文档 AAPCS 中,对栈的描述

在这里插入图片描述
这里有比较多的细节:

  • 栈是一块连续的内存区域,可以存储函数中的局部变量
  • 当调用函数所需的参数数量超过可用寄存器个数时,多出来的参数通过栈来传递(之前讲过的)
  • full-descending:full 意味着 SP 指向最后一个有效的栈元素,即高地址栈顶,descending 表示栈向低地址方向增长,SP 会变小
  • 栈在内存中有起始地址(高地址)和终止地址(低地址),但用户程序不需要知道这些地址是多少,这些地址信息一般由操作系统维护(比如 nuttx)
  • 栈可以是固定的,也可以动态扩展
  • 固定大小栈常见于嵌入式实时系统(比如 nuttx),预先分配好一定大小的空间
  • 动态扩展栈常见于复杂操作系统(比如 linux,windows),当栈快用完时,系统可以自动扩大栈空间

帧指针 FP

帧指针是函数调用时分配的栈空间基址,为了方便访问局部变量和参数,编译器通常会将 sp 的当前值保存到一个通用寄存器中,比如 r7,然后使用 r7 作为栈空间基址来访问栈上的数据,下面来看下官方文档描述
在这里插入图片描述
这里也有比较多的细节:

  • 调试器或操作系统在进行进行 backtrace(堆栈回溯)或 异常处理 时,需要知道每个函数调用是如何嵌套的,这就需要构建一条栈帧链,通俗点也叫调用链
  • 每个函数调用生成的栈帧中,都会在栈上保留一个帧记录,这个记录有两个字段,第一个字段(低地址)指向前一个函数调用的帧指针,第二个字段(高地址)保存当前函数被调用时 LR 寄存器的原始值(即返回地址),其实就是之前 blog 看到的这个操作
    在这里插入图片描述
  • 当某个帧记录的前一个帧指针地址为 0,说明这已经是最外层的函数,后面没有调用者了,比如 main 或启动代码
  • 编译器可以自由决定把帧记录放在栈帧的哪个位置(一般进入调用函数后先保存下帧记录)
  • 调用函数时,在新的帧记录完全构造完成之前,不能更新帧指针 FP,确保在中断或异常发生时,堆栈状态是完整的,不会出现部分构造的帧记录,导致回溯失败

先分析到这里,下篇再分析

http://www.dtcms.com/wzjs/542938.html

相关文章:

  • 一般做个网站多少钱微信商城网站怎么做的
  • 企业网站设计seo有做挂名法人和股东的网站吗
  • 开平市网站建设室内设计学习
  • 收费看电影网站建设网站设为首页代码
  • 注册网站会员有风险吗网站分析软件
  • 软文推广一般发布在哪些平台烟台做网站优化哪家好
  • 如何做百度网站产品线上推广方式都有哪些
  • 做纺织生意用什么网站好手机网络优化
  • 长治专业做网站网站gif小图标
  • 云南网站建设网站运营莱州一中网站
  • 织梦后台怎么做网站地图做古玩的网站
  • 没有域名 有公网ip 建网站可以五大建设是指什么
  • 盗版小说网站怎么赚钱房源管理免费系统
  • 网站功能说明怎么做企业网站建设研究
  • 高端定制网站建设公司seo优化网
  • 阿里网站建设费用盘锦网站变建设
  • 中山网站建设设计绍兴网站建设公司电话
  • 上海微网站公司网络舆情监测处置制度
  • php网站开发需要学什么软件百度开户公司
  • 公司做网站 需要解决哪些问题公司官网网站如何建立
  • 网站由谁备案秦皇岛网站制作源码
  • 汕尾住房和建设局网站首页新网站建设银行提升转账额度
  • 子目录网站合适做服装的国际网站
  • 静态网站 后台高端定制网站建设制作
  • 在线爱情动做网站校园网站源码php
  • 外贸建站深圳哪些网站是503错误代码
  • 兄弟们资源分享潍坊seo教程
  • 如皋电子商城网站建设广东电商网站建设
  • 百度云网站入口岳阳网站建设有哪些
  • 网站项目建设流程建筑类网站的推荐理由