Bootstrap

C语言之函数调用流程

调用函数所用信息

  • 函数的返回地址
  • 函数的参数
  • 临时变量
  • 保存的上下文:包括在函数调用前后需要保持不变的寄存器
//函数从左到右,还是从右向左压栈
int fun(int a,int b )
{
	int t_a = a;
	int t_b = b;
	return t_a + t_b;
}

int main()
{
	int ret = 0;
	ret = fun(10,20);
	printf("ret = %d\n",ret);
}

在这里插入图片描述
当频繁调用的时候,宏函数没有压栈入栈的开销,只是预处理器进行简单的文本替换。

实际遇到的ARM函数调用过程分析

Bug描述

遇到Bus Fault错误,错误产生原因:

  • 总线Fault:在取址、数据读/写、取中断向量、进入/退出中断时寄存器堆栈操作(入栈/出栈)时检测到内存访问错误。
  • 实际调试发现是栈溢出的问题
    在这里插入图片描述
    看到SUB.W SP, SP, #66560共大约66K。占用66K堆栈
    在这里插入图片描述
    运行到这里时出错,在任务中分配的堆栈不够用了。

ARM函数调用过程分析

函数内外跳转的指令mov和BL

  • (1)mov pc,<跳转地址>
    向程序计数器PC(寄存器R15一般用做PC)直接写跳转地址,4GB连续空间内任意跳转。
  • (2)B,BL,BLX, BX完成在当前指令向前或向后32MB的地址空间跳转。跳转的是一个相对当前PC值的一个偏移量,它的值由汇编器计算得出。BL常用,带返回地址的跳转,跳转之前在LR(连接寄存器)中保存当前PC的内容,为返回做准备。BL的用法:
1.	BL NEXT; //跳转到NEXT  
2.	...  
3.	  
4.	NEXT;  
5.	...  
6.	  
7.	MOV PC,LR; //从被调用函数返回

在这里插入图片描述

1.	int func(int a, int b, int c, int d)  
2.	{  
3.	   return 1;  
4.	}  
5.	  
6.	int main()  
7.	{  
8.	   int i = 1, j = 2;  
9.	   func(i, j, 3, 4);  
10.	   return 0;  
11.	}

在这里插入图片描述

main函数开辟的栈区和堆区

main函数内的栈区和堆区(没有free)的情况下,子函数都能使用。
在这里插入图片描述

栈的生长方向和内存存放的方向

  • 栈往地址小的地方生长
int test(void)
{
	int a=10;
	int b=20;
	int c=30;
	int d=40;
	printf("%x\n",&a); //0xa000 FFFF    //高地址
	printf("%x\n",&b); //0xa000 FFFC
	printf("%x\n",&c); //0xa000 FFF8
	printf("%x\n",&d); //0xa000 FFF4    //低地址
}
  • 内存生长方向
    小端模式:高位放在高地址,低位放在低地址

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;