裸机开发之汇编、寄存器

一、什么是汇编?为什么学汇编?

        在之前写控制代码的时候就在想:底层是怎么控制的?后来经过学习知道之前所编写的代码都是应用层代码,顾名思义就是在系统写好的底层之上调用系统函数。原以为底层是指写系统写好的底层函数,类似于写linux系统函数read、open、close之类的函数。但是再往下挖:read、open这类函数的下一层是什么?经过系统性查资料,总结了下面的流程:

         从上面的图可以知晓:linux系统所提供的IO函数属于应用层,并未涉及到最底层。open、read等函数通过file_operation结构体去调用驱动程序中的自定义的接口函数。所说的写驱动就是写自定义的device_open()、device_close()、device_write()、device_read()、device_ioctl()函数这些名字随便起。

1.1 那么这些自己编写的驱动函数是如何写入硬件设备中?

        众所周知机器所能识别的只有0和1二进制码,如果想要写入硬件设备,就要转换成二进制码写给机械。那么就又引入一个问题:

我们所写的C语言代码,怎么转换成二进制码?转换成机械识别的指令?

      提一下C语言编译流程:.c---->.i----->.s------>.o-------->二进制

 1.2 由此引入汇编指令:

        汇编语言是直接与机器打交道的,机器只能读懂二进制码,在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。汇编语言是面向机器的,处于整个计算机语言层次结构的底层,故被视为一种低级语言。从上面的图可知,预处理部分是将程序中所引用的文件打开,汇编部分是将C语言转换成可被机器识别的代码,针对CPU中的寄存器进行操作。

        汇编是一种语言,和C语言一样,有自己的编写方式,不过指令个人感觉有点难懂。

知道汇编是什么了,但还是没有解决问题:使用汇编写入硬件设备,但是写进硬件设备的哪里去了?至此引入最重要的一块:寄存器。

 二、寄存器

2.1 为什么要用寄存器?

        一块成熟的板子笼统分两部分:CPU和内存,使用流程是从CPU从内存中搬出来数据使用(大致如此)。

        CPU 本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU 要用的时候就去内存读写数据。但是,CPU 的运算速度远高于内存的读写速度,为了避免被拖慢,CPU 都自带一级缓存和二级缓存。(CPU 缓存可以看作是读写速度较快的内存。)

        CPU缓存还不够快,并且数据在缓存的地址不固定,导致CPU每次读写都会拖慢速度。因此,CPU还自带寄存器:用来储存最常用的数据。也就是说,那些最频繁读写的数据(比如循环变量),都会放在寄存器里面,CPU 优先读写寄存器,再由寄存器跟内存交换数据。

        寄存器不依靠地址区分数据,而依靠名称。每一个寄存器都有自己的名称,我们告诉 CPU 去具体的哪一个寄存器拿数据,这样的速度是最快的。有人比喻寄存器是 CPU 的零级缓存。

        总结一下就是寄存器是CPU用来存储频繁读写的数据(变量之类的)

        比如硬件有个固定地址0x300000,那么想要往这个地址里面写东西的时候,就需要将地址先暂存在寄存中使用。

下面说一下寄存器种类

2.2 寄存器种类

参考文档:ARM寄存器组织(常见专用寄存器、控制寄存器CPSR)_arm cpsr-CSDN博客

        寄存器分为三种:通用寄存器、专用寄存器(有特定的用途和功能,只能存放指定内容的寄存器。常见的有sp、lr、pc寄存器)、控制寄存器CPSR

2.2.1 通用寄存器

没有指定用途,可以存放任意内容的寄存器,既可以存放地址,也可以存放参与运算的数据或者运算产生的结果。在上图中:除去FIQ模式下,r0-r12是通用寄存器。

2.2.2 栈指针寄存器 r13 SP

栈指针,用于存储当前模式下的栈顶地址。假设现在CPU要将运算结果保存到栈上,这个时候SP寄存器就会告诉CPU栈顶的位置在哪,保存完毕以后,SP指向的地址会更新。

2.2.3 链接寄存器 r14 LR

链接寄存器,也是保存指令地址,一般是发生跳转的时候,事先保存跳转指令下一条指令的地址,一般有两种用途:

1、调用函数发生跳转

        假设main函数在执行程序的时候,需要调用函数func(),这个时候会跳转到func() 函数的定义。由于执行完func()函数以后还要继续运行main函数,在跳转之前LR寄存器会保存func()函数下一条指令的地址,也就是printf函数的地址。在执行完func函数以后,只需要让PC = LR 就可以回到func()函数下一条指令的地址。

2、异常发生(产生中断)

        产生异常时,异常模式下的LR会自动保存被异常打断的指令的下一条指令的地址。(也可以理解成是一种函数跳转)。比如CPU正在忙手里的任务,突然收到了网卡发来的信号,CPU就会进入FIQ或者IRQ模式,此时CPU就会停下手里的任务,转而先去执行异常处理程序。异常处理结束后将LR的值复制到PC可实现程序返回。

        没有哪个寄存器可以检测异常产生,因为能检测的就不是异常产生了。产生异常的时候LR默认自动保存下一条指令的地址,处理完异常情况再返回。

        异常情况时要在PC特定位置执行相应错误处理,由于偏移量(地址)是固定死的。所以当发生异常情况时,会自动跳转到该异常情况的地址执行处理异常,但PC寄存器是一条指令4字节并且是按照下面的顺序存放的(系统要求给的,只能这么写)。无法在此处处理异常,因为处理异常肯定不止一条指令,所以这里指的都是b跳转到相应标签位置处理异常

 异常的8种情况,这个需要在汇编启动代码中写出来,否则无法正常运行程序:

偏移量(地址)

异常情况

注释

0x1C

FIQ

快中断

0x18

IRQ

慢中断

0x14

(Reserved)

保留异常,现在没有用

0x10

Data Abort

数据访问异常

访问合法空间的数据发现数据不存在,访问了非法的空间(越界)

0x0c

Prefetch Abort

指令预取异常, 对程序指令预取时产生的异常

0x08

Software Interrupt(SWI)

软中断

即User模式级别使用代码发出的中断

系统调用就是使用软中断从用户模式切换到特权模式的

0x04

Undefined Instruction

未定义异常

0x00

Reset

重启异常, 模式切换到Supervisor模式

  • 通常说的异常主要来自cpu内部,abort,reset等;而中断主要来自外设。

  • 从高到低的顺序依次为:Reset,Data Abort, FIQ, IRQ,Prefetch Abort,SWI(软中断),undefined Instruction 

    • 高优先级的异常会终止底先级的异常

上面的异常向量表在代码中的体现

2.2.4 程序指针寄存器 r15 PC

        程序计数器,用于存储当前取址指令的地址。我们写的程序在经过预处理、编译、汇编以后,得到的二进制机器码就是指令。这些指令是被保存在内存中的,CPU接下来要执行哪一条指令都是由PC控制的。

        我们写程序时的逻辑是顺序执行,那么CPU在执行指令的时候也是如此,在ARM状态下,每一条指令都占4个字节,所以每执行完一条指令,PC的值会自动自增4个字节(地址自增4字节),为下一次取指令做准备

2.2.5 控制寄存器 CPSR

CPSR很重要,该寄存器里面的每个位都代表了各自含义,下图有一些说明

 举个例子:比如在进行加法运算的时候,CPSR的C位(进位)会变化

 adc:要计算十进制 3389+443 ,但是只会计算和记录两位数,于是先计算了 89+43=132 ,但是你只能记住两位数,所以记下了 32,然后把进位出的1扔进了CF 暂存;然后再计算 33+4=37 ,顺便加上 CF 的进位得到 38,跟刚才的 32 组合起来得到结果3832

 相对值得注意的是工作模式,由于板子在运行程序的时候肯定会遇到各种情况,那么其应对各种情况也是有不同的工作模式。ARM总共有7个基本工作模式:

那么体现在CPSR中MODE位,不同的编码值对应不同的模式

2.3 异常处理流程

 上面说完寄存器的种类后,那么他工作的流程顺序是如何的?

在没有异常的时候,也是按照C语言执行顺序一样,按顺序执行,遇到特殊标记跳转。

在有异常的时候,那么就需要对一些寄存器进行配置,流程如下图:

三、总结

       简单了解完寄存器之后,那么可以解决第一个问题:为什么使用汇编?

  1. 汇编语言的大部分语句直接对应着机器指令,执行速度快,效率高,代码体积小

  2. 在系统程序的核心部分,以及与系统硬件频繁打交道的部分,可以使用汇编语言。比如操作系统的核心程序段。

缺点:

  1. 不同的处理器有不同的汇编语言语法和编译器,编译的程序无法在不同的处理器上执行,缺乏可移植性

  2. 难懂且工作量大

        C语言与汇编是可以交叉使用的,C语言的好处是易懂,但是要相对寄存器直接操作是很复杂的,不如汇编直接了当,毕竟汇编指令是直接操作寄存器的,可以简单了解一些汇编指令。

        自己总结的一个图,简单一点,可能具体情况也会更复杂。

        写的文章可能还会存在缺陷,我自己是这么理解的,参考了其他博主一些文章,文章内容觉得写得好就引用了一些,勿怪勿怪。关于汇编和寄存器,弄懂就好

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

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

相关文章

苹果电脑(Mac)怎么清理 itunes 备份?

苹果电脑用户广泛利用 iTunes 应用程序对 iPhone 或 iPad进行定期备份,以确保珍贵的数据安全无虞。然而,随着备份历史的增长,它们会在磁盘上积累大量空间,尤其当您频繁为多台设备备份时,存储资源可能会迅速消耗殆尽。为…

3D Web轻量化引擎HOOPS Commuicator如何从整体装配中创建破碎的装配零件和XML?

前言 虽然可以从某些本机CAD格式(其子组件驻留在单独的文件中,例如CATIA V5、Creo - Pro/E、NX或SolidWorks)创建破碎装配,但无法从整体装配文件(例如IFC、Revit)创建或3DXML。 本文介绍了一个示例&#…

学习Rust的第一天:基础知识

Introduction 介绍 I am Shafin Murani is a software development student and I am documenting every single day of my progress in learning rust. This is the first article of the series. Shafin Muranishi 是一名软件开发专业的学生,这是他在30天内记录学…

无影云电脑不能连接到本机的调试串口的解决方案

目录 概述 解决方案 云端电脑中的操作 本地USBDK驱动程序的更新 概述 我从1月份开始使用阿里的无影云电脑进行嵌入式开发板的测试,主要的原因有两个:一是平时使用的笔记本资源过于紧张,二是方便移动办公,这样我只要平时拿着开…

UDP简单总结

UDP:用户数据报协议 特点: 无连接、不可靠通信 不事先建立连接,数据按照包发,一包数据包含:自己的IP、程序端口、目的地IP、程序端口和数据(限制在64KB内) 发送方不管对方是否在线,数据在中间丢失也不管,…

备考分享丨云计算HCIE实验考试需要注意什么

去年九月底我在朋友的推荐下报考了誉天的云计算方向,在此期间我非常感谢田sir、苗苗老师和凡凡老师,每次我遇见问题找他们都能给我完完全全的解决,给我这个非科班出身的学员很大的鼓励与帮助。 我是经济学专业,毕业之后没有考研&…

java数据结构与算法刷题-----LeetCode785. 判断二分图

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 深度优先广度优先 二分图:将所有结点分成两个集合&am…

​如何使用 ArcGIS Pro 制作带贴图建筑

对于用GIS软件制作三维建筑,很多时候都是制作的建筑体块,这里为大家介绍一下怎么使用 ArcGIS Pro 制作带贴图的建筑,希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的建筑数据,除了建筑数据,常见…

Simple_SSTI_2

Simple_SSTI_2 破解思路 1、启动场景2、用kali的tplmap扫一下 1、启动场景 http://114.67.175.224:18040/ 然后机会发现 页面啥也不是,查看源码后,看了好像又没看 2、用kali的tplmap扫一下 安装tplmap【已安装,可略过】:在kali终端安装git…

GitHub 仓库 (repository) Branch - SSH clone URL - Clone in Desktop - Download ZIP

GitHub 仓库 [repository] Branch - SSH clone URL - Clone in Desktop - Download ZIP 1. Branch2. SSH clone URL3. Clone in Desktop4. Download ZIPReferences 1. Branch 显示当前分支的名称。从这里可以切换仓库内分支,查看其他分支的文件。 2. SSH clo…

A Learning-Based Approach for IP Geolocation

下载地址:Towards IP geolocation using delay and topology measurements | Proceedings of the 6th ACM SIGCOMM conference on Internet measurement 被引次数:185 Abstract 定位IP主机地理位置的能力对于在线广告和网络攻击诊断等应用程序是非常吸引力的。虽然先前的方…

CSS-浮动文字环绕布局、隐藏属性display、overflow、三角形制作、鼠标样式

文字环绕布局 CSS文字环绕布局是指在网页中让文字环绕在图片或其他元素周围的布局方式。这通常通过CSS中的float属性来实现。你可以将图片设置为float: left;或float: right;,然后在文本元素中使用clear属性来清除浮动,以确保文字不会覆盖图片。另外&am…

React路由快速入门:Class组件和函数式组件的使用

1. 介绍 在开始学习React路由之前,先了解一下什么是React路由。React Router是一个为React应用程序提供声明式路由的库。它可以帮助您在应用程序中管理不同的URL,并在这些URL上呈现相应的组件。 2. 安装 要在React应用程序中使用React路由,…

使用pytorch构建控制生成GAN(Controllable GAN)网络模型

本文为此系列的第四篇Controllable GAN,上一篇为Conditional GAN。文中使用训练好的模型和优化噪声向量来操纵生成图像的特定属性,若有不懂的无监督知识点可以看本系列第一篇。 原理 本文主要讲什么是控制生成,以及如何做到控制生成。 什么是…

设计模式学习笔记 - 设计模式与范式 -行为型:7.责任链模式(下):框架中常用的过滤器、拦截器是如何实现的?

概述 上篇文章《6.责任链模式(上):原理与实现》,学习了职责链模式的原理与实现,并且通过一个敏感词过滤框架的例子,展示了职责链模式的设计意图。本质上来说,它跟大部分设计模式一样&#xff0…

Lvs+keepalived+nginx搭建高可用负载均衡集群,爱了爱了

检查 最后启动nginx服务 135配置虚拟网卡 检查 最后启动nginx服务 Nginx.conf配置如下 关闭132的keepalived服务后 浏览器能正常访问 132在keepalived配置中加入脚本 脚本内容 132清除ipvsadm中的规则,vip不见 133收到vip 自我介绍一下,小编13年上海交大毕业&…

React ant 点击导航条闪烁

问题 : 点击当前位置会出现闪一下的效果 另一种点击方式 , 不会闪 原因 : 没有传递具体的参数给点击事件 , 导致在函数内部无法准确判断要展示哪个子菜单,可能导致页面状态的短暂变化,出现闪烁效果 代码 : // 左侧子菜单弹出const showSonMenu routeK…

【前端】学习路线

1、基础 1.1 HTML 菜鸟教程-主页:https://www.runoob.com/ 可以学习:HTML、CSS、Bootstrap等 1.2 CSS 《通用 CSS 笔记、建议与指导》 1.3 JavaScript 1)入门:JavaScript 的基本语法 2)进阶:现代 …

hive管理之ctl方式

hive管理之ctl方式 hivehive --service clictl命令行的命令 #清屏 Ctrl L #或者 ! clear #查看数据仓库中的表 show tabls; #查看数据仓库中的内置函数 show functions;#查看表的结构 desc表名 #查看hdfs上的文件 dfs -ls 目录 #执行操作系统的命令 !命令…

JVM—垃圾收集器

JVM—垃圾收集器 什么是垃圾 没有被引用的对象就是垃圾。 怎么找到垃圾 引用计数法 当对象引用消失,对象就称为垃圾。 对象消失一个引用,计数减去一,当引用都消失了,计数就会变为0.此时这个对象就会变成垃圾。 在堆内存中主…