1、概念
这里在架构文档内基本没找到栈的知识点。
栈用于局部变量的保存,或者用于超长参数传递(寄存器不足以传递).
1.1、栈管理寄存器
核架构中的堆栈管理支持用户堆栈和中断堆栈。地址寄存器A[10]、中断堆栈指针(ISP)和PSW位用于堆栈的管理。
使用[10]作为堆栈指针。该寄存器的初始内容通常由RTOS在创建任务时设置,这允许将专用堆栈区域分配给各个任务。
ISP有助于防止中断服务例程(ISR)访问专用堆栈区域,并可能干预软件管理任务的上下文。在核架构中实现了自动切换到使用ISP而不是专用堆栈指针。PSW.IS位指示哪个堆栈指针有效。
当发生中断并且中断的任务正在使用其专用堆栈(PSW.IS == 0)时,内容与中断任务的上层上下文一起保存,并且A[10](SP)与ISP的当前内容一起加载。
当发生中断或陷阱,并且中断的任务已经在使用中断堆栈(PSW.is==1)时,则不执行A[10](SP)的预加载。中断服务例程(ISR)在中断的例程离开时继续使用中断堆栈。
通常,在初始化例程期间只需要初始化ISP一次。但是,根据应用程序的需要,可以在执行过程中修改ISP。请注意,没有什么可以阻止ISR或系统服务例程在专用堆栈上执行。
注:在ISR中使用A[10](SP)由应用程序程序员自行决定。
1.1.1、地址寄存器A[10](SP)
A[10]栈指向寄存器(SP)的定义如下:
1.1.2、中断栈指向寄存器(ISP)
中断栈指向寄存器定义如下:
注:寄存器受ENDINIT保护。
2、局部变量数据类型为基础类型
2.1、测试代码,验证局部变量进行入栈和出栈的步骤
unsigned int test_SP_6(unsigned int paramA, unsigned int paramB, unsigned int paramC)
0x80000142 20 10 SUB.A a10,0x10
{
volatile unsigned int tmp_param1 = 1;
// 0x80000144 DA 01 MOV d15,0x1
// 0x80000146 74 AF ST.W [a10],d15
volatile unsigned int tmp_param2 = 2;
// 0x80000148 DA 02 MOV d15,0x2
// 0x8000014A 78 01 ST.W [a10]0x4,d15
volatile unsigned int tmp_param3 = 3;
// 0x8000014C DA 03 MOV d15,0x3
// 0x8000014E 78 02 ST.W [a10]0x8,d15
tmp_param1 = paramA + paramB;
// 0x80000150 1A 54 ADD d15,d4,d5
// 0x80000152 74 AF ST.W [a10],d15
tmp_param2 = paramB + paramC;
// 0x80000154 42 65 ADD d5,d6
// 0x80000156 89 A5 04 09 ST.W [a10]0x4,d5
tmp_param3 = paramA + paramC;
// 0x8000015A 42 64 ADD d4,d6
// 0x8000015C 89 A4 08 09 ST.W [a10]0x8,d4
return 6;
}
// 0x80000160 82 62 MOV d2,0x6
// 0x80000162 00 90 RET
// ...
unsigned int test_SP_5(unsigned int paramA)
// 0x8000010A 20 10 SUB.A a10,0x10
{
volatile unsigned int tmp_param1 = 1;
// 0x8000010C DA 01 MOV d15,0x1
// 0x8000010E 74 AF ST.W [a10],d15
volatile unsigned int tmp_param2 = 2;
// 0x80000110 DA 02 MOV d15,0x2
// 0x80000112 78 01 ST.W [a10]0x4,d15
volatile unsigned int tmp_param3 = 3;
// 0x80000114 DA 03 MOV d15,0x3
// 0x80000116 78 02 ST.W [a10]0x8,d15
volatile unsigned int tmp_param4 = 4;
// 0x80000118 DA 04 MOV d15,0x4
// 0x8000011A 78 03 ST.W [a10]0xC,d15
tmp_param1 = tmp_param1 + paramA;
// 0x8000011C 54 AF LD.W d15,[a10]
// 0x8000011E 42 4F ADD d15,d4
// 0x80000120 74 AF ST.W [a10],d15
tmp_param2 = tmp_param2 + paramA;
// 0x80000122 58 01 LD.W d15,[a10]0x4
// 0x80000124 42 4F ADD d15,d4
// 0x80000126 78 01 ST.W [a10]0x4,d15
tmp_param3 = tmp_param3 + paramA;
// 0x80000128 58 02 LD.W d15,[a10]0x8
// 0x8000012A 42 4F ADD d15,d4
// 0x8000012C 78 02 ST.W [a10]0x8,d15
tmp_param4 = tmp_param4 + paramA;
// 0x8000012E 58 03 LD.W d15,[a10]0xC
// 0x80000130 42 4F ADD d15,d4
// 0x80000132 78 03 ST.W [a10]0xC,d15
test_SP_6(5, 5, 5);
// 0x80000134 82 54 MOV d4,0x5
// 0x80000136 02 45 MOV d5,d4
// 0x80000138 02 46 MOV d6,d4
// 0x8000013A 6D 00 04 00 CALL test_SP_6 (0x80000142)
return 5;
}
// 0x8000013E 82 52 MOV d2,0x5
// 0x80000140 00 90 RET
...
unsigned int test_SP_4(unsigned int paramB)
// 0x800000E6 20 10 SUB.A a10,0x10
{
volatile unsigned int tmp_param1 = 0;
// 0x800000E8 DA 00 MOV d15,0x0
// 0x800000EA 74 AF ST.W [a10],d15
volatile unsigned int tmp_param2 = 0;
// 0x800000EC 78 01 ST.W [a10]0x4,d15
volatile unsigned int tmp_param3 = 0;
// 0x800000EE 78 02 ST.W [a10]0x8,d15
tmp_param1 = paramB + 1;
// 0x800000F0 9A 14 ADD d15,d4,0x1
// 0x800000F2 74 AF ST.W [a10],d15
tmp_param2 = paramB + 2;
// 0x800000F4 9A 24 ADD d15,d4,0x2
// 0x800000F6 78 01 ST.W [a10]0x4,d15
tmp_param3 = paramB + 3;
// 0x800000F8 9A 34 ADD d15,d4,0x3
// 0x800000FA 78 02 ST.W [a10]0x8,d15
test_SP_5(4);
// 0x800000FC 82 44 MOV d4,0x4
// 0x800000FE 6D 00 06 00 CALL test_SP_5 (0x8000010A)
return (tmp_param1 + tmp_param2);
// 0x80000102 54 A2 LD.W d2,[a10]
// 0x80000104 58 01 LD.W d15,[a10]0x4
}
// 0x80000106 42 F2 ADD d2,d15
// 0x80000108 00 90 RET
...
unsigned int test_SP_3(unsigned int paramA)
// 0x800000CC 20 08 SUB.A a10,0x8
{
volatile unsigned int tmp_param1 = 0;
// 0x800000CE DA 00 MOV d15,0x0
// 0x800000D0 74 AF ST.W [a10],d15
volatile unsigned int tmp_param2 = 0;
// 0x800000D2 78 01 ST.W [a10]0x4,d15
tmp_param1 = paramA + 1;
// 0x800000D4 9A 14 ADD d15,d4,0x1
// 0x800000D6 74 AF ST.W [a10],d15
tmp_param2 = paramA + 2;
// 0x800000D8 9A 24 ADD d15,d4,0x2
// 0x800000DA 78 01 ST.W [a10]0x4,d15
test_SP_4(3);
// 0x800000DC 82 34 MOV d4,0x3
// 0x800000DE 6D 00 04 00 CALL test_SP_4 (0x800000E6)
return 3;
}
// 0x800000E2 82 32 MOV d2,0x3
// 0x800000E4 00 90 RET
// ...
unsigned int test_SP_2(void)
// 0x800000B6 DA 64 MOV d15,0x64
// 0x800000B8 20 08 SUB.A a10,0x8
// ...
{
volatile unsigned int tmp_var = 100;
//> 0x800000B6 DA 64 MOV d15,0x64
//> ...
//> 0x800000BA 74 AF ST.W [a10],d15
tmp_var *= 2;
// 0x800000BE 54 AF LD.W d15,[a10]
// 0x800000C0 06 1F SH d15,0x1
// 0x800000C2 74 AF ST.W [a10],d15
// ...
test_SP_3(2);
// 0x800000BC 82 24 MOV d4,0x2
//> 0x800000C4 6D 00 04 00 CALL test_SP_3 (0x800000CC)
return tmp_var;
// 0x800000C8 54 A2 LD.W d2,[a10]
}
// 0x800000CA 00 90 RET
// ...
void test_SP_1(void)
{
test_SP_2();
// 0x8000002C 1D 00 45 00 J test_SP_2 (0x800000B6)
// ...
return;
}
int main(void)
{
test_SP_1();
// 0x800000AE 6D FF BF FF CALL test_SP_1 (0x8000002C)
}
// 0x800000B2 82 02 MOV d2,0x0
// 0x800000B4 00 90 RET
2.2、调试代码,步骤记录
2.2.1、执行test_SP_1()接口
A10 - 0x70009000,指向栈底;
0x70008FF0: 00000000
0x70008FF4: 00000000
0x70008FF8: 800005C8 //上一次入栈残留的数据
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.2、执行test_SP_2()接口
- 进入接口前,A10地址减8,这是编译器根据局部变量分的,大小为8的倍数。
A10 - 0x70008FF8。 - 接口执行期间所有对局部变量的操作,都直接对栈内数据进行操作。
- 初始化局部变量tmp_var时。
0x70008FF0: 00000000
0x70008FF4: 00000000
0x70008FF8: 80000064 //tmp_var初始化数据
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
- 对局部变量tmp_val数值进行*2操作
0x70008FF0: 00000000
0x70008FF4: 00000000
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.3、执行test_SP_3()接口
- 进入接口前,A10地址减8,这是编译器根据局部变量分的,大小为8的倍数。两个参数
A10 - 0x70008FF0。 - 初始化局部变量tmp_var1和tmp_var2后。
0x70008FF0: 00000000 //tmp_var1初始化值为0
0x70008FF4: 00000000 //tmp_var2初始化值为0
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
- 局部变量tmp_var1和tmp_var2执行操作后。
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.4、执行test_SP_4()接口
- 进入接口前,A10地址减16,这是编译器根据局部变量分的,大小为8的倍数。三个参数
A10 - 0x70008FE0; - 初始化局部变量tmp_var1、tmp_var2和tmp_var3后。
0x70008FE0: 00000000 //tmp_var1初始化值0
0x70008FE4: 00000000 //tmp_var2初始化值0
0x70008FE8: 00000000 //tmp_var3初始化值0
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
- 局部变量tmp_var1、tmp_var2和tmp_var3操作后。
0x70008FE0: 00000004 //tmp_var1操作后值4
0x70008FE4: 00000005 //tmp_var2操作后值5
0x70008FE8: 00000006 //tmp_var3操作后值6
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.5、执行test_SP_5()接口
- 进入接口前,A10地址减16,这是编译器根据局部变量分的,大小为8的倍数。四个参数
A10 - 0x70008FD0; - 初始化局部变量tmp_var1、tmp_var2、tmp_var3和tmp_var4后。
0x70008FD0: 00000001 //tmp_var1初始化值1
0x70008FD4: 00000002 //tmp_var2初始化值2
0x70008FD8: 00000003 //tmp_var3初始化值3
0x70008FDC: 00000004 //tmp_var4初始化值4
0x70008FE0: 00000004 //tmp_var1操作后值4
0x70008FE4: 00000005 //tmp_var2操作后值5
0x70008FE8: 00000006 //tmp_var3操作后值6
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
- 局部变量tmp_var1、tmp_var2、tmp_var3和tmp_var4操作后。
0x70008FD0: 00000005 //tmp_var1操作后值5
0x70008FD4: 00000006 //tmp_var2操作后值6
0x70008FD8: 00000007 //tmp_var3操作后值7
0x70008FDC: 00000008 //tmp_var4操作后值8
0x70008FE0: 00000004 //tmp_var1操作后值4
0x70008FE4: 00000005 //tmp_var2操作后值5
0x70008FE8: 00000006 //tmp_var3操作后值6
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.6、执行test_SP_6()接口
- 进入接口前,A10地址减16,这是编译器根据局部变量分的,大小为8的倍数。三个参数
A10 - 0x70008FC0; - 初始化局部变量tmp_var1、tmp_var2、tmp_var3后。
0x70008FC0: 0000000A //tmp_var1操作后值10
0x70008FC4: 0000000A //tmp_var2操作后值10
0x70008FC8: 0000000A //tmp_var3操作后值10
0x70008FCC: 00000000 //预留的
0x70008FD0: 00000005 //tmp_var1操作后值5
0x70008FD4: 00000006 //tmp_var2操作后值6
0x70008FD8: 00000007 //tmp_var3操作后值7
0x70008FDC: 00000008 //tmp_var4操作后值8
0x70008FE0: 00000004 //tmp_var1操作后值4
0x70008FE4: 00000005 //tmp_var2操作后值5
0x70008FE8: 00000006 //tmp_var3操作后值6
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //tmp_var1操作后值为3
0x70008FF4: 00000004 //tmp_var2操作后值为4
0x70008FF8: 800000C8 //tmp_var*2后数值
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.7、出栈步骤
- 退出test_SP_6()接口
A10 - 0x70008FD0; - 退出test_SP_5()接口
A10 - 0x70008FE0; - 退出test_SP_4()接口
A10 - 0x70008FF0; - 退出test_SP_3()接口
A10 - 0x70008FF8; - 退出test_SP_2()接口
A10 - 0x70009000; - 退出test_SP_1()接口
A10 - 0x70009000; - 栈内数据不变化
0x70008FC0: 0000000A //上一次入栈残留的数据
0x70008FC4: 0000000A //上一次入栈残留的数据
0x70008FC8: 0000000A //上一次入栈残留的数据
0x70008FCC: 00000000 //预留的
0x70008FD0: 00000005 //上一次入栈残留的数据
0x70008FD4: 00000006 //上一次入栈残留的数据
0x70008FD8: 00000007 //上一次入栈残留的数据
0x70008FDC: 00000008 //上一次入栈残留的数据
0x70008FE0: 00000004 //上一次入栈残留的数据
0x70008FE4: 00000005 //上一次入栈残留的数据
0x70008FE8: 00000006 //上一次入栈残留的数据
0x70008FEC: 00000000 //预留的
0x70008FF0: 00000003 //上一次入栈残留的数据
0x70008FF4: 00000004 //上一次入栈残留的数据
0x70008FF8: 800000C8 //上一次入栈残留的数据
0x70008FFC: 80000652 //上一次入栈残留的数据
0x70009000: 00000000
2.2.8、疑问
1、退出接口,进行出栈时,A10是如何知道出栈块大小的?
3、局部变量数据类型为结构体
3.1、测试代码,验证局部变量进行入栈和出栈的步骤
void test_SP_8(TestParam_S paramA)
// 0x800000D4 20 10 SUB.A a10,0x10
{
volatile TestParam_S tmp_param1;
volatile unsigned int tmp_param2 = 0;
// 0x800000D6 DA 00 MOV d15,0x0
// 0x800000D8 78 03 ST.W [a10]0xC,d15
tmp_param1 = paramA;
// 0x800000DA 49 AF 10 0A LEA a15,[a10]0x10
// 0x800000DE 40 A2 MOV.AA a2,a10
// 0x800000E0 A0 24 MOV.A a4,0x2
// 0x800000E2 44 FF LD.W d15,[a15+]0x4
// 0x800000E4 64 2F ST.W [a2+]0x4,d15
// 0x800000E6 FC 4E LOOP a4,0x800000E2
tmp_param2 = 1;
// 0x800000E8 DA 01 MOV d15,0x1
// 0x800000EA 78 03 ST.W [a10]0xC,d15
}
// 0x800000EC 00 90 RET
// ...
int main(void)
// 0x800000AE 20 18 SUB.A a10,0x18
{
TestParam_S tmp_param;
tmp_param.param1 = 1;
// 0x800000B0 DA 01 MOV d15,0x1
// 0x800000B2 78 03 ST.W [a10]0xC,d15
tmp_param.param2 = 2;
// 0x800000B4 DA 02 MOV d15,0x2
// 0x800000B6 78 04 ST.W [a10]0x10,d15
tmp_param.param3 = 3;
// 0x800000B8 DA 03 MOV d15,0x3
// 0x800000BA 89 AF 14 08 ST.B [a10]0x14,d15
test_SP_8(tmp_param);
// 0x800000BE 49 AF 0C 0A LEA a15,[a10]0xC
// 0x800000C2 40 A2 MOV.AA a2,a10
// 0x800000C4 A0 24 MOV.A a4,0x2
// 0x800000C6 44 FF LD.W d15,[a15+]0x4
// 0x800000C8 64 2F ST.W [a2+]0x4,d15
// 0x800000CA FC 4E LOOP a4,0x800000C6
// 0x800000CC 6D 00 04 00 CALL test_SP_8 (0x800000D4)
}
// 0x800000D0 82 02 MOV d2,0x0
// 0x800000D2 00 90 RET
3.2、调试代码,步骤记录
A10 - 0x70009000;
3.2.1、执行main()接口
- 进入接口前,A10地址减0x18,这是编译器根据局部变量分的,大小为8的倍数。
A10 - 0x70008FE8; - 初始化局部变量tmp_param后。
0x70008FE0: 00000000
0x70008FE4: 00000000
0x70008FE8: 00000000
0x70008FEC: 00000000
0x70008FF0: 00000000
0x70008FF4: 00000001 //tmp_param.param1初始化值
0x70008FF8: 00000002 //tmp_param.param2初始化值
0x70008FFC: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70009000: 00000000
- 调用test_SP_8()接口前,栈内容
0x70008FE0: 00000000
0x70008FE4: 00000000
0x70008FE8: 00000001 //tmp_param.param1复制值
0x70008FEC: 00000002 //tmp_param.param2复制值
0x70008FF0: 80000503 //tmp_param.param3复制值
0x70008FF4: 00000001 //tmp_param.param1初始化值
0x70008FF8: 00000002 //tmp_param.param2初始化值
0x70008FFC: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70009000: 00000000
3.2.2、执行test_SP_8()接口
- 进入接口时,A10地址减0x10,这是编译器根据局部变量分的,大小为8的倍数。
A10 - 0x70008FD8; - 初始化局部变量tmp_param1和tmp_param2后。
0x70008FD0: 00000000
0x70008FD4: 00000000
0x70008FD8: 00000000 //test_SP_8()接口中tmp_param1.param1初始值
0x70008FDC: 00000000 //test_SP_8()接口中tmp_param1.param2初始值
0x70008FE0: 00000000 //test_SP_8()接口中tmp_param1.param3初始值
0x70008FE4: 00000000 //test_SP_8()接口中tmp_param2初始值
0x70008FE8: 00000001 //tmp_param.param1复制值
0x70008FEC: 00000002 //tmp_param.param2复制值
0x70008FF0: 80000503 //tmp_param.param3复制值
0x70008FF4: 00000001 //tmp_param.param1初始化值
0x70008FF8: 00000002 //tmp_param.param2初始化值
0x70008FFC: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70009000: 00000000
- 局部变量tmp_param1和tmp_param2赋值后。
0x70008FD0: 00000000
0x70008FD4: 00000000
0x70008FD8: 00000001 //test_SP_8()接口中tmp_param1.param1赋值值
0x70008FDC: 00000002 //test_SP_8()接口中tmp_param1.param2赋值值
0x70008FE0: 80000503 //test_SP_8()接口中tmp_param1.param3赋值值
0x70008FE4: 00000001 //test_SP_8()接口中tmp_param2赋值值
0x70008FE8: 00000001 //tmp_param.param1复制值
0x70008FEC: 00000002 //tmp_param.param2复制值
0x70008FF0: 80000503 //tmp_param.param3复制值
0x70008FF4: 00000001 //tmp_param.param1初始化值
0x70008FF8: 00000002 //tmp_param.param2初始化值
0x70008FFC: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70009000: 00000000
3.2.3、出栈步骤
- 退出test_SP_8()接口
A10 - 0x70008FE8; - 退出main()接口
A10 - 0x70009000;
4、接口参数传入为指针
4.1、测试代码,验证局部变量进行入栈和出栈的步骤
void test_SP_8(TestParam_S * paramA)
// 0x800000C6 20 10 SUB.A a10,0x10
{
volatile TestParam_S tmp_param1;
volatile unsigned int tmp_param2 = 0;
// 0x800000C8 DA 00 MOV d15,0x0
// 0x800000CA 78 03 ST.W [a10]0xC,d15
tmp_param1 = *paramA;
// 0x800000CC 40 AF MOV.AA a15,a10
// 0x800000CE A0 22 MOV.A a2,0x2
// 0x800000D0 44 4F LD.W d15,[a4+]0x4
// 0x800000D2 64 FF ST.W [a15+]0x4,d15
// 0x800000D4 FC 2E LOOP a2,0x800000D0
tmp_param2 = 1;
// 0x800000D6 DA 01 MOV d15,0x1
// 0x800000D8 78 03 ST.W [a10]0xC,d15
}
// 0x800000DA 00 90 RET
// ...
int main(void)
// 0x800000AE 20 10 SUB.A a10,0x10
{
TestParam_S tmp_param;
tmp_param.param1 = 1;
// 0x800000B0 DA 01 MOV d15,0x1
// 0x800000B2 74 AF ST.W [a10],d15
tmp_param.param2 = 2;
// 0x800000B4 DA 02 MOV d15,0x2
// 0x800000B6 78 01 ST.W [a10]0x4,d15
tmp_param.param3 = 3;
// 0x800000B8 DA 03 MOV d15,0x3
// 0x800000BA 2C A8 ST.B [a10]0x8,d15
test_SP_8(&tmp_param);
// 0x800000BC 40 A4 MOV.AA a4,a10
// 0x800000BE 6D 00 04 00 CALL test_SP_8 (0x800000C6)
}
// 0x800000C2 82 02 MOV d2,0x0
// 0x800000C4 00 90 RET
4.2、调试代码,步骤记录
4.2.1、执行main()接口
- 进入接口时,A10地址减0x10,这是编译器根据局部变量分的,大小为8的倍数。
A10 - 0x70008FE0; - 初始化局部变量tmp_param后。
0x70008FF0: 00000001 //tmp_param.param1初始化值
0x70008FF4: 00000002 //tmp_param.param2初始化值
0x70008FF8: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70008FFC: 00000000 //预留
0x70009000: 00000000
4.2.2、执行test_SP_8()接口
- 进入接口时,A10地址减0x10,这是编译器根据局部变量分的,大小为8的倍数。
A10 - 0x70008FD0; - 局部变量tmp_param1和tmp_param2赋值后。
0x70008FE0: 00000001 //test_SP_8()接口中tmp_param1.param3赋值值
0x70008FE4: 00000002 //test_SP_8()接口中tmp_param2赋值值
0x70008FE8: 80000503 //tmp_param.param1赋值值
0x70008FEC: 00000001 //tmp_param.param2赋值值
0x70008FF0: 00000001 //tmp_param.param1初始化值
0x70008FF4: 00000002 //tmp_param.param2初始化值
0x70008FF8: 80000503 //tmp_param.param3,800005是上一次入栈数据未清理,03是初始化值
0x70008FFC: 800005CA //上次入栈残留数据
0x70009000: 00000000
4.2.3、出栈步骤
- 退出test_SP_8()接口
A10 - 0x70008FF0; - 退出main()接口
A10 - 0x70009000;