赞
踩
FreeRTOS系列(1):基础知识——中断嵌套
FreeRTOS系列文章(2):PendSV功能,为什么需要PendSV
FreeRTOS系列文章(3): 为什么将SysTick和PendSV的优先级设置为最低
FreeRTOS系列文章(4): MDK软件仿真 + Debug-(printf)-Viewer使用方法
在裸机程序中,任务是顺序执行的,编译器将裸机程序编译成汇编程序,然后链接成可执行程序,可执行程序烧录到CPU上,CPU就会顺序执行程序,对于CPU来说,子程序也仅仅是一个跳转命令,所以我们的裸机程序的调度是编译器+CPU自动运行来实现任务的调度的。
嵌入式RTOS的一个核心功能就是任务调度,不管是时间片调度,还是优先级调度。所谓任务调度,简单的说就是操作系统控制任务运行的切换,而不是由CPU(CPU只做中断的调度)来调度,即操作系统接管了应用程序的调度。为了方便理解,我们可以打个比方,裸机程序相当于一家小型公司,老板就是CPU,裸机程序相当于公司业务,业务决策,流转都是由老板一人统一协调安排。而嵌入式RTOS则相当于一个大型公司,老板是CPU,但是已经不管具体的事儿了,只负责审批流程,而OS则是CEO,负责业务的分发,安排,当然了,OS的运行规范,需要遵循CPU的标准规范。
所以我们就有必要分析一下C语言程序在CPU中的运行原理,毕竟OS的调度也是在CPU的运行规则基础上来实现的。
高级语言(C、go、rust) |
---|
汇编语言 |
机器码 |
CPU执行的程序最终形态是机器码。机器码就是各种数字,数字对应逻辑门电路的开关,通过晶振作为心跳,来周期执行机器码。
汇编程序最终转换为机器码,即汇编程序是最接近机器码的编程语言,相比机器码,汇编语言还是有辨识度的,起码是给程序员看的。由于汇编语言的底层+可辨识特点,汇编语言是程序员唯一能够直接操控CPU的编程语言,也是因为这一原因,几乎所有的OS系统的起始代码,都是汇编语言,因为开始的时候要面向CPU编程。而且OS的任务调度,涉及到任务上下文切换的都需要汇编,因为上下文切换意味着控制CPU PC的跳转。
虽然汇编语言效率高,接近底层,而且又能直接操控CPU底层,但因为太底层,完全属于上古语言,对于程序员来说很不友好,所以目前除了CPU启动、OS底层调度会使用汇编,其他地方几乎看不到汇编的使用场景了,倒不是因为难,而是因为太麻烦了。所以现在的应用程序均使用高级语言来编写。比如C、go、rust、java等。
CPU内核的运行,都是面向寄存器的,可能很多人都有印象,CPU内核中的通用寄存器数量是非常少的,以Cortex-M3举例,其只有R0~R15,共16个用来计算的寄存器(其他外设寄存器不算),不管多么复杂的程序,CPU运行不是基于内存来运算的,而是基于R0-R15寄存器来运行的,即在CPU内核中,都是基于R0-R15来计算的,不直接对接内存。
打个比方,CPU/MCU相当于一个公司,内核相当于CEO,CEO不会直接管理底层员工,CPU只对接各个部门的经理,部门经理就相当于各个寄存器,而底层员工相当于外设,公司在运转时,底层员工工作,然后汇报给部门经理,部门经理再汇报给CEO,CEO根据部门经理的汇报内容,来进行决策。然后将决策结果反馈给部门经理,部门经理再返回到底层员工,底层员工再去执行。
将上述生活举例,映射到CPU内核,则是:外围硬件(底层员工)执行硬件工作,将执行结果推送到寄存器(汇报给部门经理),CPU内核使用寄存器的内容进行计算(CEO基于部门经理的汇报,来决策),CPU内核计算结果返回给寄存器(CEO的决策反馈给部门经理),寄存器再反馈给外围硬件(部门经理将结果下达给底层员工),外围硬件执行动作(底层员工执行)。
栈是一种数据结构,但是在C语言程序中,栈不仅代表了数据结构,更代表了C程序运行以来的临时存储中间数据的内存,前面说道,CPU内核可使用的通用寄存器数量非常少,哪怕是Cortex-M3也只有16个,对于复杂的应用程序,这16个寄存器好像是远远不够的,那么怎么办呢?有人可能会说,就不能多造些寄存器吗?造它几十亿寄存器。这就涉及到CPU内核的制造工艺了,用书面的解释说,外围硬件很容易造,CPU的内核寄存器很难造,因为寄存器的功能太特别了,直接对接CPU内核,而且完全可以通过提升软件的复杂度(多绕绕 + 堆栈)来实现少量的寄存器就够用。而栈就是为了解决这个问题,举个最简单的例子,如果我们一个子程序有20个参数,那16个寄存器肯定是不够的,怎么办呢? 我们可以将10个参数的值存放到一块可检索的内存空间里,什么时候使用了,直接从内存空间里取,反正CPU一次不会执行多行程序,这样就实现了,在少量的寄存器下,CPU照样能够完美运行程序员写出的复杂程序。
栈的数据结构比较特殊,数据的存入由高地址向地址,数据的取出则是由低地址到高地址,数据先进后出。很像弹夹中压子弹操作。
栈帧的严谨解释比较麻烦,这里我们可以简单的理解为,就是上面说的,一个函数的运行,CPU或者OS会自动给该函数分配一块栈空间,存放这各种寄存器、静态变量、局部变量、返回值等。方便CPU运行函数过程使用。
又称为“压栈”,简单的说就是将要保存的数据,比如寄存器、返回值等存入堆栈。
即从栈中读取数据,从低地址向高地址。
程序正常运行过程中,遇到中断或任务切换,即需要从当前程序位置,跳转到另外一段程序运行时,需要保存现场,执行完中断或另外任务后,再返回,使用保存的现场数据复现,即恢复现场,然后继续执行。
前面说了那么多,都只是概念的介绍,想要深刻的理解CPU运行原理,我们还是需要扒开CPU的外壳,从CPU内部角度,来查看CPU的运行原理。本文我们就以STM32F103 CPU平台为例,写一个简单的逻辑程序,涉及到多个子函数调度,子函数的参数不通,从2个到15个,之所以设计多个参数,就是为了看看,当参数比较多,寄存器个数明显不够用时,CPU时如何解决,并顺利执行程序的。
示例源程序
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
#include "led.h"
#include "delay.h"
#include "sys.h"
#include <stdio.h>
int add2_calc(int a1, int a2)
{
int ret = 0;
ret += a1;
ret += a2;
return ret;
}
int add3_calc(int a1, int a2, int a3)
{
int ret = 0;
ret += a1;
ret += a2;
ret += a3;
return ret;
}
int add4_calc(int a1, int a2, int a3, int a4)
{
int ret = 0;
ret += a1;
ret += a2;
ret += a3;
ret += a4;
return ret;
}
int add5_calc(int a1, int a2, int a3, int a4, int a5)
{
int ret = 0;
ret += a1;
ret += a2;
ret += a3;
ret += a4;
ret += a5;
return ret;
}
int add15_calc(int a1, int a2, int a3, int a4, int a5,
int a6, int a7, int a8, int a9, int a10,
int a11, int a12, int a13, int a14, int a15)
{
int ret = 0;
ret += a1;
ret += a2;
ret += a3;
ret += a4;
ret += a5;
ret += a6;
ret += a7;
ret += a8;
ret += a9;
ret += a10;
ret += a11;
ret += a12;
ret += a13;
ret += a14;
ret += a15;
return ret;
}
int main(void)
{
int a1 = 1;
int a2 = 2;
int a3 = 3;
int a4 = 4;
int a5 = 5;
int a6 = 6;
int a7 = 7;
int a8 = 8;
int a9 = 9;
int a10 = 10;
int a11 = 11;
int a12 = 12;
int a13 = 13;
int a14 = 14;
int a15 = 15;
int ret, ret2, ret3, ret4, ret5, ret15;
ret2 = add2_calc(a1, a2);
ret3 = add3_calc(a1, a2, a3);
ret4 = add4_calc(a1, a2, a3, a4);
ret5 = add5_calc(a1, a2, a3, a4, a5);
ret15 = add15_calc(a1, a2, a3, a4, a5,
a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15);
ret = ret2 + ret3 + ret4 + ret5 + ret15;
return ret;
}
汇编程序(包含运行顺序)
0x08000128 03EB DCW 0x03EB
0x0800012A 0800 DCW 0x0800
0x0800012C 03EB DCW 0x03EB
0x0800012E 0800 DCW 0x0800
__main:
0x08000130 F8DFD010 LDR.W sp,[pc,#16] ; @0x08000144
_main_scatterload:
0x08000134 F000F95E BL.W 0x080003F4 __scatterload
__main_after_scatterload:
0x08000138 4800 LDR r0,[pc,#0] ; @0x0800013C
0x0800013A 4700 BX r0
0x0800013C 01C9 DCW 0x01C9
0x0800013E 0800 DCW 0x0800
__rt_lib_shutdown_fini:
0x08000140 F3AF8000 NOP.W
__rt_final_cpp:
0x08000144 0400 DCW 0x0400
0x08000146 2000 DCW 0x2000
7: {
0x08000148 4602 MOV r2,r0 ;17 LR=0x0800020B SP=0x2000037C PC=0x08000148
8: int ret = 0;
0x0800014A 2000 MOVS r0,#0x00 ;18 LR=0x0800020B SP=0x2000037C PC=0x0800014A
9: ret += a1;
0x0800014C 4410 ADD r0,r0,r2 ;19 LR=0x0800020B SP=0x2000037C PC=0x0800014C
10: ret += a2;
11: return ret;
0x0800014E 4408 ADD r0,r0,r1 ;20 LR=0x0800020B SP=0x2000037C PC=0x0800014E
12: }
13:
14: int add3_calc(int a1, int a2, int a3)
0x08000150 4770 BX lr ;21 LR=0x0800020B SP=0x2000037C PC=0x08000150
15: {
0x08000152 B510 PUSH {r4,lr} ;23 LR=0x08000217 SP=0x2000037C PC=0x08000152
0x08000154 4603 MOV r3,r0 ;23
16: int ret = 0;
0x08000156 2000 MOVS r0,#0x00 ;24 LR=0x08000217 SP=0x20000374 PC=0x08000156
17: ret += a1;
0x08000158 4418 ADD r0,r0,r3 ;25 LR=0x08000217 SP=0x20000374 PC=0x08000158
18: ret += a2;
0x0800015A 4408 ADD r0,r0,r1 ;26 LR=0x08000217 SP=0x20000374 PC=0x0800015A
19: ret += a3;
20: return ret;
0x0800015C 4410 ADD r0,r0,r2 ;27 LR=0x08000217 SP=0x20000374 PC=0x0800015C
21: }
22:
23: int add4_calc(int a1, int a2, int a3, int a4)
0x0800015E BD10 POP {r4,pc} ;28 LR=0x08000217 SP=0x20000374 PC=0x0800015E
24: {
0x08000160 B530 PUSH {r4-r5,lr} ;30 LR=0x08000225 SP=0x2000037C PC=0x08000160
0x08000162 4604 MOV r4,r0 ;30
25: int ret = 0;
0x08000164 2000 MOVS r0,#0x00 ;31 LR=0x08000225 SP=0x20000370 PC=0x08000164
26: ret += a1;
0x08000166 4420 ADD r0,r0,r4 ;32 LR=0x08000225 SP=0x20000370 PC=0x08000166
27: ret += a2;
0x08000168 4408 ADD r0,r0,r1 ;33 LR=0x08000225 SP=0x20000370 PC=0x08000168
28: ret += a3;
0x0800016A 4410 ADD r0,r0,r2 ;34 LR=0x08000225 SP=0x20000370 PC=0x0800016A
29: ret += a4;
30: return ret;
0x0800016C 4418 ADD r0,r0,r3 ;35 LR=0x08000225 SP=0x20000370 PC=0x0800016C
31: }
32:
33: int add5_calc(int a1, int a2, int a3, int a4, int a5)
0x0800016E BD30 POP {r4-r5,pc} ;36 LR=0x08000225 SP=0x20000370 PC=0x0800016E
34: {
0x08000170 B570 PUSH {r4-r6,lr} ;38 LR=0x08000235 SP=0x2000037C PC=0x08000170
0x08000172 4604 MOV r4,r0 ;38 LR=0x08000235 SP=0x2000036C
0x08000174 9D04 LDR r5,[sp,#0x10] ;38 LR=0x08000235 SP=0x2000036C
35: int ret = 0;
0x08000176 2000 MOVS r0,#0x00 ;39 LR=0x08000235 SP=0x2000036C PC=0x08000176
36: ret += a1;
0x08000178 4420 ADD r0,r0,r4 ;40 LR=0x08000235 SP=0x2000036C PC=0x08000178
37: ret += a2;
0x0800017A 4408 ADD r0,r0,r1 ;41 LR=0x08000235 SP=0x2000036C PC=0x0800017A
38: ret += a3;
0x0800017C 4410 ADD r0,r0,r2 ;42 LR=0x08000235 SP=0x2000036C PC=0x0800017C
39: ret += a4;
0x0800017E 4418 ADD r0,r0,r3 ;43 LR=0x08000235 SP=0x2000036C PC=0x0800017E
40: ret += a5;
41: return ret;
0x08000180 4428 ADD r0,r0,r5 ;44 LR=0x08000235 SP=0x2000036C PC=0x08000180
42: }
43:
44: int add15_calc(int a1, int a2, int a3, int a4, int a5,
45: int a6, int a7, int a8, int a9, int a10,
46: int a11, int a12, int a13, int a14, int a15)
0x08000182 BD70 POP {r4-r6,pc} ;45 LR=0x08000235 SP=0x2000036C PC=0x08000182
47: {
0x08000184 E92D4FF0 PUSH {r4-r11,lr} ;47 LR=0x08000259 SP=0x2000037C PC=0x08000184
0x08000188 4604 MOV r4,r0 ;47 LR=0x08000259 SP=
0x0800018A AD09 ADD r5,sp,#0x24 ;47 LR=0x08000259 SP=
0x0800018C E89510E0 LDM r5,{r5-r7,r12} ;47 LR=0x08000259 SP=
0x08000190 E9DDAB0F LDRD r10,r11,[sp,#0x3C] ;47 LR=0x08000259 SP=
0x08000194 E9DD890D LDRD r8,r9,[sp,#0x34] ;47 LR=0x08000259 SP=
48: int ret = 0;
0x08000198 2000 MOVS r0,#0x00 ;48 LR=0x08000259 SP=0x20000358 PC=0x08000198
49: ret += a1;
0x0800019A 4420 ADD r0,r0,r4 ;49 LR=0x08000259 SP=0x20000358 PC=0x0800019A
50: ret += a2;
0x0800019C 4408 ADD r0,r0,r1 ;50 LR=0x08000259 SP=0x20000358 PC=0x0800019C
51: ret += a3;
0x0800019E 4410 ADD r0,r0,r2 ;51 LR=0x08000259 SP=0x20000358 PC=0x0800019E
52: ret += a4;
0x080001A0 4418 ADD r0,r0,r3 ;52 LR=0x08000259 SP=0x20000358 PC=0x080001A0
53: ret += a5;
0x080001A2 4428 ADD r0,r0,r5 ;53 LR=0x08000259 SP=0x20000358 PC=0x080001A2
54: ret += a6;
0x080001A4 4430 ADD r0,r0,r6 ;54 LR=0x08000259 SP=0x20000358 PC=0x080001A4
55: ret += a7;
0x080001A6 4438 ADD r0,r0,r7 ;55 LR=0x08000259 SP=0x20000358 PC=0x080001A6
56: ret += a8;
0x080001A8 4460 ADD r0,r0,r12 ;56 LR=0x08000259 SP=0x20000358 PC=0x080001A8
57: ret += a9;
0x080001AA 4440 ADD r0,r0,r8 ;57 LR=0x08000259 SP=0x20000358 PC=0x080001AA
58: ret += a10;
0x080001AC 4448 ADD r0,r0,r9 ;58 LR=0x08000259 SP=0x20000358 PC=0x080001AC
59: ret += a11;
0x080001AE 4450 ADD r0,r0,r10 ;59 LR=0x08000259 SP=0x20000358 PC=0x080001AE
60: ret += a12;
0x080001B0 4458 ADD r0,r0,r11 ;57 LR=0x08000259 SP=0x20000358 PC=0x080001B0
61: ret += a13;
0x080001B2 F8DDE044 LDR lr,[sp,#0x44] ;58 LR=0x08000259 SP=0x20000358 PC=0x080001B2
0x080001B6 4470 ADD r0,r0,lr ;58 LR=0x0000000D SP=0x20000358
62: ret += a14;
0x080001B8 F8DDE048 LDR lr,[sp,#0x48] ;59 LR=0x0000000D SP=0x20000358 PC=0x080001B8
0x080001BC 4470 ADD r0,r0,lr ;59 LR=0x0000000E SP=0x20000358
63: ret += a15;
64: return ret;
0x080001BE F8DDE04C LDR lr,[sp,#0x4C] ;60 LR=0x0000000E SP=0x20000358 PC=0x080001BE
0x080001C2 4470 ADD r0,r0,lr ;60 LR=0x0000000F SP=0x20000358
65: }
66:
67:
68: int main(void)
0x080001C4 E8BD8FF0 POP {r4-r11,pc} ;61 LR=0x0000000F SP=0x20000358 PC=0x080001C4
69: {
0x080001C8 E92D4FF0 PUSH {r4-r11,lr} ;0-3 LR=0x08000411 SP=0x20000400 PC=0x080003C8 R0=0x080001C9 R1=0x08000400 R2=0
0x080001CC B098 SUB sp,sp,#0x60 ;0-3 LR=0x08000411 SP=0x20000XXX PC=0x080003C8 R0=0x080001C9 R1=0x08000400 R2=0
70: int a1 = 1;
0x080001CE 2001 MOVS r0,#0x01 ;1 LR=0x08000411 SP=0x2000037C PC=0x080001CE
0x080001D0 9017 STR r0,[sp,#0x5C] ;1 LR=0x08000411 SP=0x2000037C
71: int a2 = 2;
0x080001D2 2002 MOVS r0,#0x02 ;2 LR=0x08000411 SP=0x2000037C PC=0x080001D2
0x080001D4 9016 STR r0,[sp,#0x58] ;2 LR=0x08000411 SP=0x2000037C
72: int a3 = 3;
0x080001D6 2003 MOVS r0,#0x03 ;3 LR=0x08000411 SP=0x2000037C PC=0x080001D6
0x080001D8 9015 STR r0,[sp,#0x54] ;3 LR=0x08000411 SP=0x2000037C
73: int a4 = 4;
0x080001DA 2004 MOVS r0,#0x04 ;4 LR=0x08000411 SP=0x2000037C PC=0x080001DA
0x080001DC 9014 STR r0,[sp,#0x50] ;4 LR=0x08000411 SP=0x2000037C
74: int a5 = 5;
0x080001DE 2405 MOVS r4,#0x05 ;5 LR=0x08000411 SP=0x2000037C PC=0x080001DE
75: int a6 = 6;
0x080001E0 2006 MOVS r0,#0x06 ;6 LR=0x08000411 SP=0x2000037C PC=0x080001E0
0x080001E2 9013 STR r0,[sp,#0x4C] ;6 LR=0x08000411 SP=0x2000037C
76: int a7 = 7;
0x080001E4 2507 MOVS r5,#0x07 ;7 LR=0x08000411 SP=0x2000037C PC=0x080001E4
77: int a8 = 8;
0x080001E6 2608 MOVS r6,#0x08 ;8 LR=0x08000411 SP=0x2000037C PC=0x080001E6
78: int a9 = 9;
0x080001E8 2709 MOVS r7,#0x09 ;9 LR=0x08000411 SP=0x2000037C PC=0x080001E8
79: int a10 = 10;
0x080001EA F04F080A MOV r8,#0x0A ;10 LR=0x08000411 SP=0x2000037C PC=0x080001EA
80: int a11 = 11;
0x080001EE F04F090B MOV r9,#0x0B ;11 LR=0x08000411 SP=0x2000037C PC=0x080001EE
81: int a12 = 12;
0x080001F2 F04F0A0C MOV r10,#0x0C ;12 LR=0x08000411 SP=0x2000037C PC=0x080001F2
82: int a13 = 13;
0x080001F6 F04F0B0D MOV r11,#0x0D ;13 LR=0x08000411 SP=0x2000037C PC=0x080001F6
83: int a14 = 14;
0x080001FA 200E MOVS r0,#0x0E ;14 LR=0x08000411 SP=0x2000037C PC=0x080001FA
0x080001FC 9012 STR r0,[sp,#0x48] ;14 LR=0x08000411 SP=0x2000037C
84: int a15 = 15;
85:
86: int ret, ret2, ret3, ret4, ret5, ret15;
87:
0x080001FE 200F MOVS r0,#0x0F ;15 LR=0x08000411 SP=0x2000037C PC=0x080001FE
0x08000200 9011 STR r0,[sp,#0x44] ;15 LR=0x08000411 SP=0x2000037C
88: ret2 = add2_calc(a1, a2);
0x08000202 E9DD1016 LDRD r1,r0,[sp,#0x58] ;16 LR=0x08000411 SP=0x2000037C PC=0x08000202
0x08000206 F7FFFF9F BL.W 0x08000148 add2_calc ;16 LR=0x0800020B SP=0x2000037C
0x0800020A 900F STR r0,[sp,#0x3C] ;21 LR=0x0800020B SP=0x2000037C
89: ret3 = add3_calc(a1, a2, a3);
0x0800020C E9DD2115 LDRD r2,r1,[sp,#0x54] ;22 LR=0x0800020B SP=0x2000037C PC=0x0800020C
0x08000210 9817 LDR r0,[sp,#0x5C] ;22
0x08000212 F7FFFF9E BL.W 0x08000152 add3_calc ;22
0x08000216 900E STR r0,[sp,#0x38] ;28 LR=0x08000217 SP=0x2000037C
90: ret4 = add4_calc(a1, a2, a3, a4);
0x08000218 E9DD3214 LDRD r3,r2,[sp,#0x50] ;29 LR=0x08000217 SP=0x2000037C PC=0x08000218
0x0800021C E9DD1016 LDRD r1,r0,[sp,#0x58] ;29
0x08000220 F7FFFF9E BL.W 0x08000160 add4_calc ;29
0x08000224 900D STR r0,[sp,#0x34] ;36 LR=0x08000225 SP=0x2000037C
91: ret5 = add5_calc(a1, a2, a3, a4, a5);
0x08000226 9400 STR r4,[sp,#0x00] ;37 LR=0x08000225 SP=0x2000037C PC=0x08000226
0x08000228 E9DD3214 LDRD r3,r2,[sp,#0x50] ;37 LR=0x08000225 SP=0x2000037C
0x0800022C E9DD1016 LDRD r1,r0,[sp,#0x58] ;37 LR=0x08000225 SP=0x2000037C
0x08000230 F7FFFF9E BL.W 0x08000170 add5_calc ;37 LR=0x08000225 SP=0x2000037C
0x08000234 900C STR r0,[sp,#0x30] ;45 LR=0x08000235 SP=0x2000037C
92: ret15 = add15_calc(a1, a2, a3, a4, a5,
93: a6, a7, a8, a9, a10,
94: a11, a12, a13, a14, a15);
95:
0x08000236 E9DD0111 LDRD r0,r1,[sp,#0x44] ;46 LR=0x08000235 SP=0x2000037C PC=0x08000236
0x0800023A AA03 ADD r2,sp,#0x0C ;46 LR=0x08000235 SP=0x2000037C
0x0800023C E8A20FC0 STM r2!,{r6-r11} ;46 LR=0x08000235 SP=0x2000037C
0x08000240 E9CD1009 STRD r1,r0,[sp,#0x24] ;46 LR=0x08000235 SP=0x2000037C
0x08000244 9813 LDR r0,[sp,#0x4C] ;46 LR=0x08000235 SP=0x2000037C
0x08000246 E9CD0501 STRD r0,r5,[sp,#0x04] ;46 LR=0x08000235 SP=0x2000037C
0x0800024A 9400 STR r4,[sp,#0x00] ;46 LR=0x08000235 SP=0x2000037C
0x0800024C E9DD3214 LDRD r3,r2,[sp,#0x50] ;46 LR=0x08000235 SP=0x2000037C
0x08000250 E9DD1016 LDRD r1,r0,[sp,#0x58] ;46 LR=0x08000235 SP=0x2000037C
0x08000254 F7FFFF96 BL.W 0x08000184 add15_calc ;46 LR=0x08000235 SP=0x2000037C
0x08000258 900B STR r0,[sp,#0x2C] ;61 LR=0x0000000F SP=0x2000037C
96: ret = ret2 + ret3 + ret4 + ret5 + ret15;
97:
0x0800025A E9DD100E LDRD r1,r0,[sp,#0x38] ;62 LR=0x0000000F SP=0x2000037C PC=0x0800025A
0x0800025E 4401 ADD r1,r1,r0 ;62 LR=0x0000000F SP=0x2000037C
0x08000260 980D LDR r0,[sp,#0x34] ;62 LR=0x0000000F SP=0x2000037C
0x08000262 4401 ADD r1,r1,r0 ;62 LR=0x0000000F SP=0x2000037C
0x08000264 980C LDR r0,[sp,#0x30] ;62 LR=0x0000000F SP=0x2000037C
0x08000266 4401 ADD r1,r1,r0 ;62 LR=0x0000000F SP=0x2000037C
0x08000268 980B LDR r0,[sp,#0x2C] ;62 LR=0x0000000F SP=0x2000037C
0x0800026A 4408 ADD r0,r0,r1 ;62 LR=0x0000000F SP=0x2000037C
0x0800026C 9010 STR r0,[sp,#0x40] ;62 LR=0x0000000F SP=0x2000037C
98: return ret;
0x0800026E 9810 LDR r0,[sp,#0x40] ;63 LR=0x0000000F SP=0x2000037C PC=0x0800026E
99: }
0x08000270 B018 ADD sp,sp,#0x60 ;64 LR=0x0000000F SP=0x2000037C PC=0x08000270
0x08000272 E8BD8FF0 POP {r4-r11,pc}
31: }
32:
#####################...中断代码省略 ##############################################################
151: LDR R0, =SystemInit
0x080003D0 4806 LDR r0,[pc,#24] ; @0x080003EC
152: BLX R0
0x080003D2 4780 BLX r0
153: LDR R0, =__main
0x080003D4 4806 LDR r0,[pc,#24] ; @0x080003F0 ;0-1 LR=0x0800036D SP=0x20000400 PC=0x080003D4 RO=0x08000000
154: BX R0
155: ENDP
156:
157: ; Dummy Exception Handlers (infinite loops which can be modified)
158:
159: NMI_Handler PROC
160: EXPORT NMI_Handler [WEAK]
0x080003D6 4700 BX r0 ;0-2 LR=0x0800036D SP=0x20000400 PC=0x080003D6 R0=0x08000131
161: B .
162: ENDP
163: HardFault_Handler\
164: PROC
165: EXPORT HardFault_Handler [WEAK]
0x080003D8 E7FE B 0x080003D8 NMI_Handler
166: B .
167: ENDP
168: MemManage_Handler\
169: PROC
170: EXPORT MemManage_Handler [WEAK]
0x080003DA E7FE B 0x080003DA HardFault_Handler
171: B .
172: ENDP
173: BusFault_Handler\
174: PROC
175: EXPORT BusFault_Handler [WEAK]
0x080003DC E7FE B 0x080003DC MemManage_Handler
176: B .
177: ENDP
178: UsageFault_Handler\
179: PROC
180: EXPORT UsageFault_Handler [WEAK]
0x080003DE E7FE B 0x080003DE BusFault_Handler
181: B .
182: ENDP
183: SVC_Handler PROC
184: EXPORT SVC_Handler [WEAK]
0x080003E0 E7FE B 0x080003E0 UsageFault_Handler
185: B .
186: ENDP
187: DebugMon_Handler\
188: PROC
189: EXPORT DebugMon_Handler [WEAK]
0x080003E2 E7FE B 0x080003E2 SVC_Handler
190: B .
191: ENDP
192: PendSV_Handler PROC
193: EXPORT PendSV_Handler [WEAK]
0x080003E4 E7FE B 0x080003E4 DebugMon_Handler
194: B .
195: ENDP
196: SysTick_Handler PROC
197: EXPORT SysTick_Handler [WEAK]
0x080003E6 E7FE B 0x080003E6 PendSV_Handler
198: B .
0x080003E8 E7FE B 0x080003E8 SysTick_Handler
324: B .
0x080003EA E7FE B 0x080003EA Default_Handler
0x080003EC 036F DCW 0x036F
0x080003EE 0800 DCW 0x0800
0x080003F0 0131 DCW 0x0131
0x080003F2 0800 DCW 0x0800
0x080003F4 4C06 LDR r4,[pc,#24] ; @0x08000410
0x080003F6 4D07 LDR r5,[pc,#28] ; @0x08000414
0x080003F8 E006 B 0x08000408
0x080003FA 68E0 LDR r0,[r4,#0x0C]
0x080003FC F0400301 ORR r3,r0,#0x01
0x08000400 E8940007 LDM r4,{r0-r2}
0x08000404 4798 BLX r3
0x08000406 3410 ADDS r4,r4,#0x10
0x08000408 42AC CMP r4,r5
0x0800040A D3F6 BCC 0x080003FA
0x0800040C F7FFFE94 BL.W 0x08000138 __main_after_scatterload
0x08000410 0438 DCW 0x0438
0x08000412 0800 DCW 0x0800
0x08000414 0448 DCW 0x0448
0x08000416 0800 DCW 0x0800
0x08000418 E002 B 0x08000420
0x0800041A C808 LDM r0!,{r3}
############################ 省略 ##########################
详细分析序列图
通过上面的详细分析,可以发现:
(1)C语言或高级语言是给程序员看的,对于CPU来说,没有高级语言,只有机器码。
(2)机器码的上层是汇编语言,高级语言编译后,会转换成汇编语言。
(3)汇编语言在逻辑上是非常简洁的,或者说是非常简单的,只有加、减、乘、除、跳转、入栈、出栈、存储、加载等逻辑,CPU的内核是面向寄存器进行操作的,由于汇编语言是最接近CPU的编程语言,所以汇编程序就是很底层的,基本逻辑就是将程序中的变量加载到寄存器,然后再通过寄存器计算,然后再将结果存入到另外的寄存器。
(4)CPU内核的寄存器数量是非常少的,我们程序中会有大量的局部变量、静态变量、常量等等,都使用寄存器是不可能的,所以我们需要将这些变量都临时放置在堆栈里。
(5)堆栈是内存中的一块连续可用的空间,因为4中的原因,稍微复杂的函数都需要堆栈存放临时变量。
(7)对于裸机程序,在启动阶段会准备好堆栈空间,后面所有的程序运行都是使用这一堆栈。
(8)高级语言中我们是看不到堆栈的,也看不到汇编,这是因为编译器会自动的将我们的高级语言程序翻译成汇编程序,而且编译器非常的强大,能够自动计算出我们需要的堆栈,自动转换最优的汇编映射,自动的计算运行过程中临时变量存储堆栈的方案,所以可以这么说,高级语言必然要依赖强大的编译器,这个编译器既可以是GCC,也可以是程序员使用的IDE。
(9)程序的调用伴随着保存现场、上下文切换、执行、恢复现场、退出,当然还有最重要的LR、PC寄存器的操作,在裸机程序中,IDE会自动的帮我们去做。
(10)9中所说,IDE会帮助裸机程序做切换工作,在OS系统中,OS最核心的工作就是任务调度,而任务本质上就是程序,所以任务调度也是一种程序调用,由于OS需要自动任务调度,所以OS需要做IDE的工作,即保存现场、上下文切换、恢复现场、退出等,而这些由于只能通过直接操控寄存器,而只有汇编语言可以直接操作寄存器,所以操作系统的任务切换功能必须要通过汇编实现,这也是目前为止几乎所有的OS都要包含少量汇编程序的原因。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。