鸿蒙内核源码分析(汇编基础篇) | CPU在哪里打卡上班

本篇通过拆解一段很简单的汇编代码来快速认识汇编,为读懂鸿蒙汇编打基础.系列篇后续将逐个剖析鸿蒙的汇编文件.

汇编很简单

  • 第一: 要认定汇编语言一定是简单的,没有高深的东西,无非就是数据的搬来搬去,运行时数据主要待在两个地方:内存和寄存器。寄存器是CPU内部存储器,离运算器最近,所以最快.

  • 第二: 运行空间(栈空间)就是CPU打卡上班的地方,内核设计者规定谁请CPU上班由谁提供场地,用户程序提供的场地叫用户栈,敏感工作CPU要带回公司做,公司提供的场地叫内核栈,敏感工作叫系统调用,系统调用的本质理解是CPU要切换工作模式即切换办公场地。

  • 第三:CPU的工作顺序是流水线的,它只认指令,而且只去一个地方(指向代码段的PC寄存器)拿指令运算消化。指令集是告诉外界我CPU能干什么活并提供对话指令,汇编语言是人和CPU能愉快沟通不拧巴的共识语言。一一对应了CPU指令,又能确保记性不好的人类能模块化的设计idea, 先看一段C编译成汇编代码再来说模块化。

square(c -> 汇编)

//编译器: armv7-a clang (trunk)
//++++++++++++ square(c -> 汇编)++++++++++++++++++++++++
int square(int a,int b){
    return a*b;
}
square(int, int):
        sub     sp, sp, #8     @sp减去8,意思为给square分配栈空间,只用2个栈空间完成计算
        str     r0, [sp, #4]   @第一个参数入栈
        str     r1, [sp]       @第二个参数入栈
        ldr     r1, [sp, #4]   @取出第一个参数给r1
        ldr     r2, [sp]       @取出第二个参数给r2
        mul     r0, r1, r2     @执行a*b给R0,返回值的工作一直是交给R0的
        add     sp, sp, #8     @函数执行完了,要释放申请的栈空间
        bx      lr             @子程序返回,等同于mov pc,lr,即跳到调用处

fp(c -> 汇编)

//++++++++++++ fp(c -> 汇编)++++++++++++++++++++++++
int fp(int b)
{
    int a = 1;
    return square(a+b,a+b);
}
fp(int):
        push    {r11, lr}      @r11(fp)/lr入栈,保存调用者main的位置
        mov     r11, sp        @r11用于保存sp值,函数栈开始位置 
        sub     sp, sp, #8     @sp减去8,意思为给fp分配栈空间,只用2个栈空间完成计算
        str     r0, [sp, #4]   @先保存参数值,放在SP+4,此时r0中存放的是参数
        mov     r0, #1         @r0=1
        str     r0, [sp]       @再把1也保存在SP的位置
        ldr     r0, [sp]       @把SP的值给R0
        ldr     r1, [sp, #4]   @把SP+4的值给R1
        add     r1, r0, r1     @执行r1=a+b
        mov     r0, r1         @r0=r1,用r0,r1传参
        bl      square(int, int)@先mov lr, pc 再mov pc square(int, int)   
        mov     sp, r11        @函数执行完了,要释放申请的栈空间 
        pop     {r11, lr}      @弹出r11和lr,lr是专用标签,弹出就自动复制给lr寄存器
        bx      lr             @子程序返回,等同于mov pc,lr,即跳到调用处

main(c -> 汇编)

//++++++++++++ main(c -> 汇编)++++++++++++++++++++++++
int main()
{
    int sum = 0;
    for(int a = 0;a < 100; a++){
        sum = sum + fp(a);
    }
    return sum;
}
main:
        push    {r11, lr}      @r11(fp)/lr入栈,保存调用者的位置
        mov     r11, sp        @r11用于保存sp值,函数栈开始位置
        sub     sp, sp, #16    @sp减去16,意思为给main分配栈空间,只用4个栈空间完成计算
        mov     r0, #0         @初始化r0
        str     r0, [r11, #-4] @执行sum = 0
        str     r0, [sp, #8]   @sum将始终占用SP+8的位置
        str     r0, [sp, #4]   @a将始终占用SP+4的位置
        b       .LBB1_1        @跳到循环开始位置
.LBB1_1:                       @循环开始位置入口
        ldr     r0, [sp, #4]   @取出a的值给r0
        cmp     r0, #99        @跟99比较
        bgt     .LBB1_4        @大于99,跳出循环 mov pc .LBB1_4
        b       .LBB1_2        @继续循环,直接 mov pc .LBB1_2
.LBB1_2:                       @符合循环条件入口
        ldr     r0, [sp, #8]   @取出sum的值给r0,sp+8用于写SUM的值
        str     r0, [sp]       @先保存SUM的值,SP的位置用于读SUM值
        ldr     r0, [sp, #4]   @r0用于传参,取出A的值给r0作为fp的参数
        bl      fp(int)        @先mov lr, pc再mov pc fp(int)
        mov     r1, r0         @fp的返回值为r0,保存到r1
        ldr     r0, [sp]       @取出SUM的值
        add     r0, r0, r1     @计算新sum的值,由R0保存
        str     r0, [sp, #8]   @将新sum保存到SP+8的位置
        b       .LBB1_3        @无条件跳转,直接 mov pc .LBB1_3
.LBB1_3:                       @完成a++操作入口
        ldr     r0, [sp, #4]   @SP+4中记录是a的值,赋给r0
        add     r0, r0, #1     @r0增加1
        str     r0, [sp, #4]   @把新的a值放回SP+4里去
        b       .LBB1_1        @跳转到比较 a < 100 处
.LBB1_4:                       @循环结束入口
        ldr     r0, [sp, #8]   @最后SUM的结果给R0,返回值的工作一直是交给R0的
        mov     sp, r11        @函数执行完了,要释放申请的栈空间
        pop     {r11, lr}      @弹出r11和lr,lr是专用标签,弹出就自动复制给lr寄存器
        bx      lr             @子程序返回,跳转到lr处等同于 MOV PC, LR

代码有点长,都加了注释,如果能直接看懂那么恭喜你,鸿蒙内核的6个汇编文件基于也就懂了。这是以下C文件全貌

文件全貌

#include <stdio.h>
#include <math.h>

int square(int a,int b){
    return a*b;
}

int fp(int b)
{
    int a = 1;
    return square(a+b,a+b);
}

int main()
{
    int sum = 0;
    for(int a = 0;a < 100; a++){
        sum = sum + fp(a);
    }
    return sum;
}

代码很简单谁都能看懂,代码很典型,具有代表性,有循环,有判断,有运算,有多级函数调用。编译后的汇编代码基本和C语言的结构差不太多,区别是对循环的实现用了四个模块,四个模块也好理解:
一个是开始块(LBB1_1), 一个符合条件的处理块(LBB1_2),一个条件发生变化块(LBB1_3),最后收尾块(LBB1_4).

按块逐一剖析.

先看最短的那个

int square(int a,int b){
    return a*b;
}
//编译成
square(int, int):
        sub     sp, sp, #8     @sp减去8,意思为给square分配栈空间,只用2个栈空间完成计算
        str     r0, [sp, #4]   @第一个参数入栈
        str     r1, [sp]       @第二个参数入栈
        ldr     r1, [sp, #4]   @取出第一个参数给r1
        ldr     r2, [sp]       @取出第二个参数给r2
        mul     r0, r1, r2     @执行a*b给R0,返回值的工作一直是交给R0的
        add     sp, sp, #8     @函数执行完了,要释放申请的栈空间
        bx      lr             @子程序返回,等同于mov pc,lr,即跳到调用处

首先上来一句 sub sp, sp, #8 等同于 sp = sp - 8 ,CPU运行需要场地,这个场地就是栈 ,SP是指向栈的指针,表示此时用栈的刻度. 代码和鸿蒙内核用栈方式一样,都采用了递减满栈的方式(FD).

什么是递减满栈? 递减指的是栈底地址高于栈顶地址,栈的生长方向是递减的, 满栈指的是SP指针永远指向栈顶. 每个函数都有自己独立的栈底和栈顶,之间的空间统称栈帧.可以理解为分配了一块

区域给函数运行,sub sp, sp, #8 代表申请2个栈空间,一个栈空间按四个字节算.

用完要不要释放?当然要,add sp, sp, #8 就是释放栈空间. 是一对的,减了又加回去,空间就归还了.

ldr r1, [sp, #4] 的意思是取出SP+4这个虚拟地址的值给r1寄存器,而SP的指向并没有改变的,还是在栈顶, 为什么要+呢, +就是往回数, 定位到分配的栈空间上.

一定要理解递减满栈,这是关键! 否则读不懂内核汇编代码.

入参方式

一般都是通过寄存器(r0…r10)传参,fp调用square之前会先将参数给(r0…r10)

        add     r1, r0, r1     @执行r1=a+b
        mov     r0, r1         @r0=r1,用r0,r1传参
        bl      square(int, int)@先mov lr, pc 再mov pc square(int, int) 

到了square中后,先让 r0,r1入栈,目的是保存参数值, 因为 square中要用r0,r1 ,

        str     r0, [sp, #4]   @先入栈保存第一个参数
        str     r1, [sp]       @再入栈保存第二个参数
        ldr     r1, [sp, #4]   @再取出第一个参数给r1,(a*b)中a值
        ldr     r2, [sp]       @再取出第二个参数给r2,用于计算 (a*b)中b值

是不是感觉这段汇编很傻,直接不保存计算不就完了吗,这个是流程问题,编译器统一先保存参数,至于你想怎么用它不管,也管不了.

另外返回值都是默认统一给r0保存. square中将(a*b)的结果给了r0,回到fp中取出R0对fp来说这就是square的返回值,这是规定.

函数调用
main 和 fp 中都需要调用其他函数,所以都出现了

        push    {r11, lr}
        //....
        pop     {r11, lr}

这哥俩也是成对出现的,这是函数调用的必备装备,作用是保存和恢复调用者的现场,例如 main -> fp, fp要保存main的栈帧范围和指令位置, lr保存的是main函数执行到哪个指令的位置, r11的作用是指向main的栈顶位置,如此fp执行完后return回main的时候,先mov pc,lr, PC寄存器的值一变, 表示执行的代码就变了,又回到了main的指令和栈帧继续未完成的事业.

内存和寄存器数据怎么搬?

数据主要待在两个地方:内存和寄存器. 寄存器<->寄存器 , 内存<->寄存器 , 内存<->内存 搬运指令都不一样.

        str     r1, [sp]       @ 寄存器->内存
        ldr     r1, [sp, #4]   @ 内存->寄存器

这又是一对,用于 内存<->寄存器之间,熟知的 mov r0, r1 用于 寄存器<->寄存器

追问三个问题
第一:如果是可变参数怎么办? 100个参数怎么整, 通过寄存器总共就12个,不够传参啊

第二:返回值可以有多个吗?

第三:数据搬运可以不经过CPU吗?

也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线。大家可以进行参考学习:https://qr21.cn/FV7h05

①全方位,更合理的学习路径
路线图包括ArkTS基础语法、鸿蒙应用APP开发、鸿蒙能力集APP开发、次开发多端部署开发、物联网开发等九大模块,六大实战项目贯穿始终,由浅入深,层层递进,深入理解鸿蒙开发原理!

②多层次,更多的鸿蒙原生应用
路线图将包含完全基于鸿蒙内核开发的应用,比如一次开发多端部署、自由流转、元服务、端云一体化等,多方位的学习内容让学生能够高效掌握鸿蒙开发,少走弯路,真正理解并应用鸿蒙的核心技术和理念。

③实战化,更贴合企业需求的技术点
学习路线图中的每一个技术点都能够紧贴企业需求,经过多次真实实践,每一个知识点、每一个项目,都是码牛课堂鸿蒙研发团队精心打磨和深度解析的成果,注重对学生的细致教学,每一步都确保学生能够真正理解和掌握。

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:https://qr21.cn/FV7h05

如何快速入门:

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr21.cn/FV7h05

大厂鸿蒙面试题::https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/584409.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云服务器(Ubuntu22)上的MySQL8更改为大小写不敏感

因为windows上默认的mysql8.0是大小写不敏感的&#xff0c;部署到服务器上之后发现ubuntu默认的是大小写敏感&#xff0c;所以为了不更改代码&#xff0c;需要将mysql数据库设置为大小写不敏感的。 &#xff01;&#xff01;&#xff01;重要一定要做好数据库的备份&#xff0…

【Vue3】openlayers加载瓦片地图并手动标记坐标点

目录 一、创建Vue3项目 二、openlayers加载瓦片地图&#xff08;引js文件版&#xff09; 2.1 将以下的文件复制到public下 2.2 index.html引入ol脚本 2.3 删除项目自带的HelloWorld.vue&#xff0c;创建Map.vue 2.4 编码Map.vue 2.5 修改App.vue 2.6 启动项目测试 三、…

与Apollo共创生态:Apollo 7周年大会带给我的启发和心得

Apollo 7周年大会 前不久的Apollo 7周年大会&#xff0c;吸引到我这个对自动驾驶有着浓厚兴趣的开发者&#xff0c;真的精彩&#xff0c;受益匪浅。Apollo 7周年大会展示了Apollo在自动驾驶领域的创新成果&#xff0c;探讨自动驾驶技术的未来发展趋势&#xff0c;并推动自动驾…

关键技术自主可控,中国移动发布大云磐石DPU芯片,速率达400Gbps

4月28日&#xff0c;中国移动在2024算力网络大会上正式发布大云磐石DPU&#xff0c;该芯片带宽达到400Gbps&#xff0c;为国内领先水平&#xff0c;将应用于移动云新一代大云磐石DPU产品&#xff0c;实现关键技术自主可控。 据介绍&#xff0c;DPU是一种专注于数据处理的处理器…

Python多线程并不是真的并行执行

Python多线程虽然能够利用多个CPU核执行计算&#xff0c;但并不能真正执行多线程并行计算。因为在Python中&#xff0c;有一个全局解释锁&#xff08;GlobalInterpreter Lock&#xff0c;GIL&#xff09;&#xff0c;该锁的存在使得在同一个时间只有一个线程执行任务&#xff0…

KKView远程控制2.0版本发布,TeamViewer面临巨大挑战

KKView远程控制2.0版本发布&#xff0c;TeamViewer面临巨大挑战 近日&#xff0c;备受瞩目的远程控制软件KKView发布了其全新2.0版本&#xff0c;KKView以其独特的创新性和用户友好的设计&#xff0c;为远程办公、远程培训等领域提供了更加高效、便捷的解决方案。 KKView远程…

DVWA靶场

DVWA是指Damn Vulnerable Web Application&#xff0c;是一个用于教育和训练网络安全人员的虚拟漏洞应用程序。DVWA模拟了一个包含了多种常见Web安全漏洞的虚拟环境&#xff0c;包括SQL注入、XSS攻击、CSRF攻击等等。通过使用DVWA&#xff0c;安全人员可以学习和实践各种Web安全…

c#数据库: 8.在窗体上显示学生信息

以上一章学生信息表为例&#xff0c;首先将查询的学生信息存储到数据集中&#xff0c;然后将数据集与数据显示控件绑定&#xff0c;从而实现学生信息在窗体上的显示 &#xff08;1&#xff09;创建一个名为StudentGridView的窗体应用程序&#xff0c;为窗体添加一个DataGridVi…

OSI 模型

OSI参考模型包括什么&#xff1a; OSI 参考模型分为七层从下往上分别是&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层和应 用层 应用层 &#xff1a; 应用层是 OSI 标准模型的最顶层&#xff0c;是直接为应用进程提供服务的。其作用是在实现多个系统应用…

2024年十五届蓝桥杯省赛大学B组真题(Java完整版)

2024年十五届蓝桥杯省赛大学B组真题&#xff08;Java&#xff09; 前言&#xff1a; 赛后一直犹豫要不要对比赛进行复盘出个题解&#xff0c;拖到了现在&#xff0c;终于也是等到比赛结果出来&#xff0c;看到没有辜负个人期望成功取得省一&#xff0c;决定在国赛前对省赛进行…

【网络原理】UDP协议 | UDP报文格式 | 校验和 | UDP的特点 | 应用层的自定义格式

文章目录 一、UDP协议1.UDP的传输流程发送方接收方 2.UDP协议报文格式&#xff1a;长度受限校验和如何校验&#xff1a;CRC算法&#xff1a;循环冗余算法md5算法&#xff1a; 2.UDP的特点 二、开发中常见的自定义格式1.xml&#xff08;古老&#xff09;2.json&#xff08;最流行…

nn.TransformerEncoderLayer详细解释,使用方法!!

nn.TransformerEncoderLayer nn.TransformerEncoderLayer 是 PyTorch 的 torch.nn 模块中提供的一个类&#xff0c;用于实现 Transformer 编码器的一个单独的层。Transformer 编码器层通常包括一个自注意力机制和一个前馈神经网络&#xff0c;中间可能还包含层归一化&#xff…

uniapp关于iconfont字体图标使用

1、打开[阿里巴巴矢量图标库](https://www.iconfont.cn/)&#xff0c;选择需要的图标添加到购物车 2、点开购物车&#xff0c;将图标添加到项目 3、点开项目&#xff0c;点击下载至本地&#xff0c;会得到一个download.zip包 4、解压download包 5、将包里的iconfont.css和iconf…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-8.1--C语言LED驱动程序

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

Q1季度阿胶电商数据分析:某黑马品牌线上销售增长超1800%

作为滋补养三大宝之一&#xff0c;阿胶具有补血滋阴、润燥止血、益智健脑、缓延衰老、强筋健骨、提高免疫力等多种功效和作用。同时阿胶被誉为“补血神器”、“美容养颜”等&#xff0c;使得其备受市场欢迎。 根据鲸参谋数据显示&#xff0c;今年Q1季度&#xff0c;在综合电商…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第15课-xcard方式跳转平行3D馆

【WEB前端2024】开源智体世界&#xff1a;乔布斯3D纪念馆-第15课-xcard方式跳转平行3D馆 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智…

记录一次大数据量接口优化过程

问题描述 记录一次大数据量接口优化过程。最近在优化一个大数据量的接口&#xff0c;是提供给安卓端APP调用的&#xff0c;因为安卓端没做分批次获取&#xff0c;接口的数据量也比较大&#xff0c;因为加载速度超过一两分钟&#xff0c;所以导致接口超时的异常&#xff0c;要让…

【C++干货基地】探索C++模板的魅力:如何构建高性能、灵活且通用的代码库(文末送书)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

天空卫士旗舰产品入选《网络安全专用产品指南》

权威认证 近日&#xff0c;中国网络安全产业联盟&#xff08;CCIA&#xff09;发布了第一版《网络安全专用产品指南》。这一权威指南中&#xff0c;天空卫士荣获殊荣&#xff0c;旗下三款尖端产品荣耀入选&#xff0c;分别是增强型Web安全网关&#xff08;ASWG&#xff09;、数…

广交会烹饪机器人用上大模型 支付宝小程序云提供技术支持

近日&#xff0c;第135届广交会正在火热进行&#xff0c;记者获悉&#xff0c;支付宝小程序云助力合作伙伴田螺云厨&#xff0c;在烹饪机器人上开始用上大模型技术。各类智能产品的亮相&#xff0c;从中国制造迈向中国创造&#xff0c;也成为广交会的一个亮点。 &#xff08;图…
最新文章