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

设计网站考虑哪些因素郑州制作网站电话133

设计网站考虑哪些因素,郑州制作网站电话133,口碑好个人品牌营销公司,泉州市知名网站建设公司大概意思就是arm每个函数开始都会将PC、LR、SP以及FP四个寄存器入栈。 下面我们看一下这四个寄存器里面保存的是什么内存 arm-linux-gnueabi-gcc unwind.c -mapcs -w -g -o unwind&#xff08;需要加上-mapcs才会严格按照上面说的入栈&#xff09; #include <stdio.h> …

 大概意思就是arm每个函数开始都会将PC、LR、SP以及FP四个寄存器入栈。

 下面我们看一下这四个寄存器里面保存的是什么内存

arm-linux-gnueabi-gcc unwind.c -mapcs -w -g -o unwind(需要加上-mapcs才会严格按照上面说的入栈)

#include <stdio.h>
#include <stdlib.h>struct stackframe {unsigned long fp;//低地址unsigned long sp;unsigned long lr;unsigned long pc;//高地址
};
void backtrace() {struct stackframe *frame = NULL;unsigned long *sp = NULL;asm volatile ("mov %0, ip" : "=g"(sp));//ip里面保存的是还未压栈的spprintf("sp poniter 0x%lx\n", sp);frame = (char*)sp - sizeof(struct stackframe);printf("fp 0x%lx, pc 0x%lx, sp 0x%lx\n", frame->fp,frame->pc, frame->sp);//通过打印栈帧里面的sp确实和ip里面的一样的/* 不知道怎么结束循环.... */for (; frame->fp < 0xdeadbeef; frame = frame->fp - sizeof(struct stackframe) + sizeof(unsigned long)) {printf("Function enter at [<%08x>] from [<%08x>]\n", frame->pc, frame->lr);}
}void f3(int c) {printf("%d\n", c);backtrace();
}
void f2(int b) {f3(b);
}
void f1(int a) {char arr[5] = {0};f2(a);
}int main(int argc, char *argv[]) {printf("programe %s\n", argv[0]);f1(1);return 0;
}

arm-linux-gnueabi-objdump -S unwind > objdump 

void backtrace() {8500:	e1a0c00d 	mov	ip, sp8504:	e92dd810 	push	{r4, fp, ip, lr, pc}8508:	e24cb004 	sub	fp, ip, #4850c:	e24dd00c 	sub	sp, sp, #12
......................................000085c0 <f3>:void f3(int c) {85c0:	e1a0c00d 	mov	ip, sp85c4:	e92dd800 	push	{fp, ip, lr, pc}85c8:	e24cb004 	sub	fp, ip, #485cc:	e24dd008 	sub	sp, sp, #8
........................................85dc:	ebffff6b 	bl	8390 <_init+0x20>backtrace();85e0:	ebffffc6 	bl	8500 <backtrace>
}85e4:	e24bd00c 	sub	sp, fp, #1285e8:	e89da800 	ldm	sp, {fp, sp, pc}85ec:	0000878c 	.word	0x0000878c000085f0 <f2>:
void f2(int b) {85f0:	e1a0c00d 	mov	ip, sp85f4:	e92dd800 	push	{fp, ip, lr, pc}85f8:	e24cb004 	sub	fp, ip, #485fc:	e24dd008 	sub	sp, sp, #88600:	e50b0010 	str	r0, [fp, #-16]f3(b);8604:	e51b0010 	ldr	r0, [fp, #-16]8608:	ebffffec 	bl	85c0 <f3>
}860c:	e24bd00c 	sub	sp, fp, #128610:	e89da800 	ldm	sp, {fp, sp, pc}00008614 <f1>:
void f1(int a) {8614:	e1a0c00d 	mov	ip, sp8618:	e92dd800 	push	{fp, ip, lr, pc}861c:	e24cb004 	sub	fp, ip, #48620:	e24dd018 	sub	sp, sp, #24
..........................................f2(a);8644:	e51b0020 	ldr	r0, [fp, #-32]8648:	ebffffe8 	bl	85f0 <f2>
}864c:	e59f3018 	ldr	r3, [pc, #24]	; 866c <f1+0x58>00008670 <main>:int main(int argc, char *argv[]) {8670:	e1a0c00d 	mov	ip, sp8674:	e92dd800 	push	{fp, ip, lr, pc}8678:	e24cb004 	sub	fp, ip, #4867c:	e24dd008 	sub	sp, sp, #88680:	e50b0010 	str	r0, [fp, #-16]8684:	e50b1014 	str	r1, [fp, #-20]printf("programe %s\n", argv[0]);8688:	e51b3014 	ldr	r3, [fp, #-20]868c:	e5933000 	ldr	r3, [r3]8690:	e59f001c 	ldr	r0, [pc, #28]	; 86b4 <main+0x44>8694:	e1a01003 	mov	r1, r38698:	ebffff3c 	bl	8390 <_init+0x20>f1(1);869c:	e3a00001 	mov	r0, #186a0:	ebffffdb 	bl	8614 <f1>return 0;86a4:	e3a03000 	mov	r3, #0
}

 上面是样例代码对应的汇编代码截取。在函数的最开头都存在如下代码

    8500:	e1a0c00d 	mov	ip, sp8504:	e92dd810 	push	{r4, fp, ip, lr, pc}8508:	e24cb004 	sub	fp, ip, #4

 就是文章最开始说的函数一开始都会将fp、sp、lr以及pc压栈。那这几个寄存器里面的内容是什么呢?

sp即栈顶指针,sp里面记录的是当前函数的栈顶位置;并且从汇编代码里面能看到先是将sp给ip,然后将ip入栈。因此栈中记录的sp位置是压栈之前的

lr用于保存函数的返回地址(若f2调用f3,那在样例代码中对应的位置就是这一行8558:    e89da800     ldm    sp, {fp, sp, pc}

pc指针,程序计数器,用于记录当前执行到哪条指令。但是由于ARM采用流水线机制。当正确读取PC时,该值为当前指令(正在执行的指令)地址+8个字节。即PC执行当前指令的下两条地址。所以这就解释了样例代码的打印是0000850c

void backtrace() {
    8500:    e1a0c00d     mov    ip, sp
    8504:    e92dd810     push    {r4, fp, ip, lr, pc}//执行到这里时,pc里面记录的是下面两条指令
    8508:    e24cb004     sub    fp, ip, #4
    850c:    e24dd00c     sub    sp, sp, #12
......................................

具体可以查看这篇文章

ARM体系结构相关杂记_这个我好像学过的博客-CSDN博客

fp:frame pointer:同样也是这段代码。sub    fp, ip, #4// fp = ip - 4。那fp其实保存的就是上一个函数的函数栈起始位置-4。这也是for循环里面下一个函数栈需要写为

for (;; frame = frame->fp - sizeof(struct stackframe) + sizeof(unsigned long))

即下一个函数栈是fp + 4 - 12

为什么是上一个函数栈呢?

我们看下面的代码f1调用f2。函数f2最开始压入的fp,这个fp寄存器里面记录的是什么值呢。它里面其实就是上一个函数里面的sub    fp, ip, #4得到的啊。ip里面又是上一个函数f1的函数栈开始位置。

000085f0 <f2>:
void f2(int b) {85f0:	e1a0c00d 	mov	ip, sp85f4:	e92dd800 	push	{fp, ip, lr, pc}85f8:	e24cb004 	sub	fp, ip, #485fc:	e24dd008 	sub	sp, sp, #88600:	e50b0010 	str	r0, [fp, #-16]f3(b);8604:	e51b0010 	ldr	r0, [fp, #-16]8608:	ebffffec 	bl	85c0 <f3>
}860c:	e24bd00c 	sub	sp, fp, #128610:	e89da800 	ldm	sp, {fp, sp, pc}00008614 <f1>:
void f1(int a) {8614:	e1a0c00d 	mov	ip, sp8618:	e92dd800 	push	{fp, ip, lr, pc}861c:	e24cb004 	sub	fp, ip, #48620:	e24dd018 	sub	sp, sp, #24
..........................................f2(a);8644:	e51b0020 	ldr	r0, [fp, #-32]8648:	ebffffe8 	bl	85f0 <f2>
}864c:	e59f3018 	ldr	r3, [pc, #24]	; 866c <f1+0x58>

因此最终的函数栈构成了下图所示。那我怎么感觉文章开始的那张图片是错的呢。。。。

 最后样例代码运行结果如下图。由于不知道怎么算回溯结束,所以程序报错了

另外程序打印出来的地址也会汇编代码吻合.具体可以看汇编信息

 

 另外用arm-linux-gnueabi-addr2line解析出来的行号也是准确的

http://www.yayakq.cn/news/561408/

相关文章:

  • 石家庄市里的网站公司自助建网站哪个便宜
  • 重庆网站建设公司的网站上海微信小程序网站建设
  • php做网站 价格建设门户网站系统的必要性
  • 阿里巴巴吧做网站wordpress简单相册
  • 营销型网站结构图软件开发包括哪些阶段
  • dede企业网站带留言板后台查询网店详情页模板
  • 网站备案后应该做什么做复刻衣服买网站
  • 信阳建设企业网站智慧团建系统网站
  • 唐山网站建设赫鸣科技网站打不开404
  • 我的世界找建筑网站网站设置请求桌面网站
  • 东莞气缸东莞网站建设网站开发如何修改字体
  • 网站制作工作室东莞浩智网站建设公司
  • 东莞市网站建设品牌拓者8室内设计网
  • 桂林出网站wordpress获取标签名
  • 专业网站设计学校网页制作软件序列号
  • 网站制作的基础网站开发行业知识新闻
  • 相亲网站上做it的骗术网站采集信息怎么做
  • 中式建筑网站平面设计公司排名前十
  • 网站做统计分析有哪些中文域名网站
  • 带后台网站建设wordpress模板大全
  • 个人网站制作多少钱哪个网站能接效果图做
  • 一个网站需要哪些备案上市公司网站建设方案
  • 宁波培训网站建设潍坊大型做网站建设的公司
  • 信宜网站开发公司在线购物系统的分析与设计
  • 建设一个最普通网站要多少钱展示网站模板下载
  • 接单子做网站做mod游戏下载网站
  • 奉贤网站制作哪个网站可以接加工单
  • 动态图网站怎么做dw如何建立网站模板
  • 家教网站建设网站建设销售秘籍
  • 企业建设网站公司简介wordpress开发主题