RTOS系列文章(5):C语言程序运行原理分析:汇编、栈、栈帧、进栈、出栈、保存现场、恢复现场、返回

17 篇文章 23 订阅
15 篇文章 121 订阅

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的运行规则基础上来实现的。

重要概念

从应用程序到CPU能执行的机器码转换层级

高级语言(C、go、rust)
汇编语言
机器码

机器码

CPU执行的程序最终形态是机器码。机器码就是各种数字,数字对应逻辑门电路的开关,通过晶振作为心跳,来周期执行机器码。

汇编

汇编程序最终转换为机器码,即汇编程序是最接近机器码的编程语言,相比机器码,汇编语言还是有辨识度的,起码是给程序员看的。由于汇编语言的底层+可辨识特点,汇编语言是程序员唯一能够直接操控CPU的编程语言,也是因为这一原因,几乎所有的OS系统的起始代码,都是汇编语言,因为开始的时候要面向CPU编程。而且OS的任务调度,涉及到任务上下文切换的都需要汇编,因为上下文切换意味着控制CPU PC的跳转。

高级语言

虽然汇编语言效率高,接近底层,而且又能直接操控CPU底层,但因为太底层,完全属于上古语言,对于程序员来说很不友好,所以目前除了CPU启动、OS底层调度会使用汇编,其他地方几乎看不到汇编的使用场景了,倒不是因为难,而是因为太麻烦了。所以现在的应用程序均使用高级语言来编写。比如C、go、rust、java等。

寄存器、CPU运行原理

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运行函数过程使用。

进栈

又称为“压栈”,简单的说就是将要保存的数据,比如寄存器、返回值等存入堆栈。

出栈

即从栈中读取数据,从低地址向高地址。

保存现场、恢复现场、返回

程序正常运行过程中,遇到中断或任务切换,即需要从当前程序位置,跳转到另外一段程序运行时,需要保存现场,执行完中断或另外任务后,再返回,使用保存的现场数据复现,即恢复现场,然后继续执行。

C程序运行原理实例分析

前面说了那么多,都只是概念的介绍,想要深刻的理解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都要包含少量汇编程序的原因。

  • 17
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FreeRTOS是一个开源的实时操作系统,用于嵌入式系统中。ELF是一种可执行文件格式,用于存储和传输可执行程序和库。 在FreeRTOS中,程序的编译后会生成一个可执行文件,通常是ELF格式。如果我们想对这个可执行文件进行反汇编,我们可以使用相应的工具。 ELF反汇编是将二进制代码转换回汇编语言的过程。它可以帮助我们理解程序的结构和执行流程,并进行调试和优化。 可以使用一些工具进行ELF反汇编,例如GNU工具链中的objdump命令。objdump可以读取ELF格式的文件,并将其转换为可读的汇编代码。 具体来说,如果我们想对FreeRTOS的ELF文件进行反汇编,我们可以使用以下命令: ``` objdump -d [可执行文件路径] ``` 这将生成一个包含汇编代码的文件,我们可以在其中查看程序的反汇编结果。 在进行ELF反汇编时,我们可以观察指令的地址、指令的类型以及操作数等信息。通过分析汇编结果,我们可以更好地理解程序的运行逻辑,并发现隐藏的问题或优化的机会。 然而,需要注意的是,反汇编并不总是能够完全还原原始源代码。因此,在进行ELF反汇编时,应该结合其他调试和性能分析工具,以全面理解和优化代码。 总之,ELF反汇编是一个有用的工具,可以帮助我们理解和优化FreeRTOS中的程序。通过分析汇编结果,我们可以更好地理解程序的执行流程和结构,从而提高嵌入式系统的性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值