从汇编角度理解C语言篇 (三) —— C语言函数的实现

发布时间:2026/11/11 8:02:30

从汇编角度理解C语言篇 (三) —— C语言函数的实现 1. C语言函数组成// 返回类型 函数名 参数列表 int add (int a, int b) { // 函数体 int ret a b; // 返回值 return ret; }在C语言中函数是执行特定任务的独立代码块。一个函数可以接收参数如果有的话执行一系列操作然后可选地返回一个值。C语言中的函数组成主要包括以下几个部分‌返回类型‌函数的返回类型指定了函数执行完成后返回值的类型。例如int、void、float、char等。void表示该函数不返回任何值。‌函数名‌这是函数的标识符用于在程序中调用该函数。函数名必须是合法的标识符且在程序中是唯一的。‌参数列表‌参数列表定义了函数执行时可以接收的数据。参数可以有零个或多个每个参数都有一个类型和一个名称。参数之间用逗号分隔。如果函数不需要参数则参数列表为空写成void例如int add(int a, int b)。‌函数体‌函数体是包含了一组执行特定任务的语句的大括号{}内的部分。这是函数的实际代码实现。‌返回值‌在函数体内部可以使用return语句返回一个值。返回值的类型必须与函数的返回类型匹配。如果函数的返回类型是void则不能使用return语句返回一个值但可以使用return;仅表示提前退出。2. C语言函数传入传出参数在读下面内容之前可以先思考一个问题为什么使用变量传入参数给函数在函数里面无法直接改变传入变量的值还是以 add 函数为例。c语言代码int add(int a, int b) { return a b; } int main(void) { add(1, 2); return 0; }对应ARM汇编代码add: 0x080001AE 4602 MOV r2, r0 ; 把r0的值给 r2寄存器 0x080001B0 1850 ADDS r0, r2, r1 ; r2和r1的值相加给r0, 用于传出参数 0x080001B2 4770 BX lr ; 跳转回函数调用地址 main: 0x080001B6 2102 MOVS r1, #0x02 ; 立即数赋值. 把 数字2 写入 r1寄存器 0x080001B8 2001 MOVS r0, #0x01 ; 把 数字1 写入 r0寄存器 0x080001BA F7FFFFF8 BL.W add (0x080001AE) ; 调用/进入 add 函数 0x080001BE 2000 MOVS r0, #0x00 ; return 0从汇编代码可以看出传入参数对函数传入参数时需要把参数传给 r 寄存器进入函数后函数再从 r 寄存器里获取数据。传出参数函数传出或者返回值时同样通过 r 寄存器向外传入参数。也就是说 r 寄存器可以作为函数传入传出的介质。以下为ARM寄存器组说明寄存器别名主要用途特殊说明R0A1函数第 1 个参数 / 函数返回值ARM 标准调用约定下函数返回值必须通过R0返回R1A2函数第 2 个参数-R2A3函数第 3 个参数-R3A4函数第 4 个参数-R4V1通用变量寄存器需被调用者保存若函数修改了R4-R11需手动保存到栈R5V2通用变量寄存器需被调用者保存-R6V3通用变量寄存器需被调用者保存-R7V4通用变量寄存器 / 帧指针FPThumb 指令集中常作为栈帧指针R8V5通用变量寄存器需被调用者保存-R9V6通用变量寄存器 / 平台寄存器部分操作系统中用作全局变量指针SBR10V7通用变量寄存器需被调用者保存-R11V8通用变量寄存器需被调用者保存-R12IP内部过程调用寄存器用于动态链接、库函数调用时的临时中转R13SP栈指针Stack Pointer指向栈顶硬件自动维护Cortex-M 为满递减栈R14LR链接寄存器Link Register保存函数 / 中断的返回地址BL指令会自动写入R15PC程序计数器Program Counter指向当前执行指令的下一条指令地址修改PC会直接跳转ARM约定R0-R3 寄存器传递函数前 4 个参数。那么如果函数大于四个参数呢聪明的你应该已经想到了内存也可以用于保存参数。ARM正是这样做的超过4个参数则进行压栈处理。操作规则传参R0-R3传递前 4 个参数超过部分压入栈返回值32 位 / 64 位结果通过R0R1返回寄存器保存R0-R3, R12由调用者保存R4-R11, LR由被调用者保存当然不同芯片架构不同编译器也会有区别这里不展开讨论。回到上面的问题为什么使用变量传入参数给函数在函数里面无法直接改变传入变量的值简单来说因为数据经过了拷贝在函数里是改变的并不是原来的变量里的内容。3. 函数调用和返回我们还是看上面的例子但只看调用和返回部分。add: 0x080001B2 4770 BX lr ; 跳转回函数调用地址 0x080001BE main: 0x080001BA F7FFFFF8 BL.W add (0x080001AE) ; 调用/进入 add 函数 0x080001BE 2000 MOVS r0, #0x00 ; return 0我们在第一篇讲过汇编代码组织方式可以按功能流程组织代码块执行不同功能时只需要跳转到对应的代码块。C语言进入到子函数也是通过跳转方式实现的跳转前BL会自动将下一条指令的地址放入LR寄存器子函数通过LR寄存器的地址返回到原来的地址。我们再看看多层嵌套函数function_2: 0x080001B8 4770 BX lr function_1: 0x080001BA B500 PUSH {lr} 0x080001C0 F7FFFFF8 BL.W function_2 (0x080001B4) 0x080001C4 BD00 POP {pc} main: 0x080001CA F7FFFFF6 BL.W function_1 (0x080001BA) 0x080001CE 2000 MOVS r0, #0x00function_1 进入子函数 function_2 前需要把 LR寄存器 PUSH压栈返回的时候POP 值直接给到PCCPU立即跳回调用者的下一行。更多层的函数嵌套也是一样的。这里有一个小技巧在调试时我们可以使用调试器的调用栈功能如果代码出现fault就能很直观的看到函数调用关系方便解bug。4. C语言代码优化经过上面的内容我们能明显发现一个问题每次调用函数都需要进行参数拷贝不仅需要消耗拷贝时间参数多的时候也消耗内存空间。另外函数调用的越深栈使用的也会越多。在使用内存资源比较小的芯片我们需要尽可能的减少资源消耗。1. 对于参数拷贝问题我们可以使用以下方法优化用宏替代简单的函数。inline 内联函数。需要注意的是内联函数代码及变量需要尽可能的少否则在内联函数展开后可能会适得其反。但其实一般情况下编译器已经能做的足够好只要我们提高编译优化等级就能很好的优化掉此类问题。2. 对于函数调用深度问题可以考虑以下方法避免过度封装函数定时器等回调函数可以设置触发标志在另一处进行具体函数处理使用事件驱动型架构降低调用层级
延伸阅读

更多相关文章

2026/11/1 3:30:45

数据治理平台与数据运营体系融合建设方案:从指标口径到最小闭环

简介:面向企业数据治理与数据运营体系建设需求,这份PPT方案按总体解决方案、平台建设方案、运营实施方案三层框架展开,适合数据治理工程师、数据平台架构师及数字化转型项目负责人参考。开篇厘清数据治理的狭义与广义定义,进而梳理…

2026/11/11 7:57:58

电工证戴眼镜吗 全国通用的实操考试关键细节

电工证戴眼镜吗 全国通用的实操考试关键细节 实操考试心里没底怕挂科,尤其是对视力有要求的项目,比如电工证考试,戴眼镜会不会影响评分?这是很多考生在备考时最关心的问题之一。尤其是在洛阳涧西区,劳务班组负责人在安排电工岗位人员时,经常遇到员工因…

2026/11/11 7:57:58

特种工证要年审吗 怎么报名才不白交培训费

特种工证要年审吗 怎么报名才不白交培训费 怕考不过白交培训费?特种工证不仅要年审,报名前这些细节你必须知道。 特种工证要年审吗?这个问题在很多打算考证或者已经拿到证的人中都很常见。实际上,特种作业操作证的有效期和复审周期,直接关系到你能不能…

2026/11/11 7:57:58

年审后电工证贴了什么证丢了怎么补办

电工证年审后贴了什么?真实经历告诉你怎么补办 证书过期了不知道怎么复审延期,我身边不少同行都遇到过这个问题,尤其是那些刚拿到证的新手电工,对年审流程一知半解,一不小心就错过了复审时间。今天就用我这些年的真实经历,和大家聊聊【年审后电工证贴了…

2026/11/11 7:57:58

商河县学电工证怎么考不挂科 网上查询成绩有技巧

商河县学电工证怎么考不挂科 网上查询成绩有技巧 实操考试心里没底怕挂科,这是很多商河县学员在报考电工证时的普遍担忧。尤其是在高压电工证、低压电工证等实操内容占比高、操作规范要求严的考试中,一次失误就可能导致整场考试失败。但好消息是,现在通过…

2026/11/11 7:57:58

西乡附近考电工证多少钱,学历不高也能考?别急,看这篇就够了

西乡附近考电工证多少钱,学历不高也能考?别急,看这篇就够了 你是不是也这样, 学历不高怕报不上名 ,担心自己连报名资格都没有,白白浪费时间和精力?别担心,今天就给你讲清楚, 西乡附近考电工证多少钱 ,以及那些你必须知道的报考真相。…

2026/11/11 7:52:58

电工作业培训记录表值不值得考?实操考试心里没底怕挂科怎么办?

电工作业培训记录表值不值得考?实操考试心里没底怕挂科怎么办? 实操考试心里没底怕挂科,这事儿我太懂了。去年我表弟考电工证,光是培训记录表就填了三遍,最后还是因为一个细节没注意被退回,差点错过了考试。很多人和他一样,对电工作业培训记录表这个东…

2026/11/10 8:12:38

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/11 0:02:26

考低压电工证通过率考试真题与备考技巧

低压电工证通过率高不高?学历不高也能考,值不值得考? 你是不是总听说电工证能帮你找高薪工作,但又担心自己学历不够,考不上?其实,低压电工证考试门槛并没有你想象中那么高,关键是方法对不对。这篇文章就告诉你, 考低压电工证通过率到底有多高 ,…

2026/11/11 0:02:26

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名 你是不是也和我一样,刚毕业就听说低压电工证学时必须达标才能上岗?可一打听,发现报名机构五花八门,价格参差不齐, 不知道去哪报名怕被中介坑…

2026/11/10 20:08:15

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑