聊一聊基础的CPU寄存器~

2023-11-16

寄存器:CPU内部的存储单元,用于存放从内存读取而来的数据(包括指令)和CPU运算的中间结果。

使用寄存器来临时存放数据而不直接操作内存原因如下:

  1. CPU的工作原理决定了有些操作只能在CPU内部进行。

  2. CPU读写寄存器的速度比读写内存的速度要快很多。

为便于交流和使用汇编语言编程,CPU厂商为每个寄存器都取了名字,如ADM64 CPU的rax、rbx、rcx等,这样就很方便的在汇编代码中直接使用寄存器的名称来进行编程,来看段Go编写的一行代码来直观的感受下寄存器的使用:

a := b + c

ADM64 Linux平台下用Go编译器编译上述代码可得如下AT&T格式的汇编代码:

mov   (%rsp),%rdx      //把变量b的值从内存中读取到寄存器rdxmov   0x8(%rsp),%rax   //把变量c的值从内存中读取到寄存器raxadd   %rdx,%rax        //把寄存器rdx和rax里面的值相加,之后将结果放回寄存器raxmov   %rax,0x10(%rsp)  //把寄存器rax中的值写回变量a所在的寄存器rsp

由上述汇编代码可以看到,一行Go代码被编译成了四行汇编指令,上述汇编代码里面的rsp、rap、rdp都是寄存器的名称(说明:AT&T格式的汇编代码中所有的寄存器名字前面都有一个%符号)。

可以看到,虽然只有四条指令,但也从侧面说明汇编代码比较简单,因为它所做的工作仅仅只是把数据在内存和寄存器中来回倒腾或是做一些基础的数学以及逻辑运算。

不同体系结构的CPU在其内部存在的寄存器的数量、类型以及名称可能会不同,本文只看ADM64 CPU这一种体系结构,这种CPU在其内部存在二十多个可直接被汇编语言中使用的调度器,还有几种仅在操作系统代码中才会出现,应用层的话,通常只会用到如下三个分类共19个调度器:

  1. 通用寄存器。共有rax、rbx、rcx、rdx、rsi、rdi、rbp、rsp、r8、r9、r10、r11、r12、r13、r14、r15这16个寄存器,CPU对它们的用途没有做特殊规定,可以自定义其用途(其中rsp、rbp这两个寄存器有特殊用途)。

  2. 程序计数寄存器(rip寄存器,也叫PC寄存器、IP寄存器)。用来存放下一条即将用来执行的指令的地址,它决定程序执行的流程。

  3. 段寄存器(fs、gs寄存器)。用来实现线程本地存储(TLS),比如ADM64 Linux下Go语言和pthread线程库都用fs存储器来实现线程的TLS(本地存储)。

上述存储器除了段寄存器是16位的,其它都是64位的,也就是八个字节,但是通用寄存器还可以当做32/16/8位存储器来使用。

不过使用的时候就需要换个名字了,比如可用eax来表示一个32位的寄存器,它使用的是rax寄存器的低32位。为方便各位查阅,下表为64位通用寄存器对应32/16/8位存储器的名称,如下:

64位 32位 16位 8位
rax eax ax al/ah
rbx ebx bx bl/bh
rcx ecx cx cl/ch
rdx edx dx dl/dh
rsi esi si -
rdi edi di -
rbp ebp bp -
rsp esp sp -
r8~r15 r8d~r15d r8w~r15w r8b~r15b

接下来看下rip、rsp、rbp这三个特殊的寄存器。

1、rip寄存器:存放CPU即将执行的下一条指令在内存中的地址。

来看段汇编语言:

0x0000000000400770: add   %rdx,%rax0x0000000000400773: mov   $0x0,%ecx

假设当前CPU正在执行第一条指令,我们可以看到,这条指令在内存中的地址就是0x0000000000400770,很明显,紧随其后的下一条将执行的指令在内存中的地址就是0x0000000000400773,此时,rip寄存器中所存储的值就是0x0000000000400773。

只需要记住,rip寄存器中存储的值不是CPU正在执行的指令在内存中的地址,而是紧随其后那一条将要被执行的指令在内存中的地址。

这里有人可能会问了,上述代码片段中并没有指令来让CPU去修改rip寄存器中的值呀,那rip寄存器是怎么实现上述功能的呢?

修改rip寄存器中的值这个操作是CPU自动控制的,不需要通过指令去修改,当然,CPU对外也提供了几条间接修改rip寄存器的指令,这个后面再详聊。

2、rsp栈顶寄存器以及rbp栈基寄存器。

上述两个寄存器都和函数调用栈相关,其中rsp寄存器一般用来存放函数调用栈的栈顶在内存中的地址,rbp寄存器通常用来存放函数的栈帧在内存中的起始地址。

编译器一般使用上述寄存器加一定偏移来访问函数局部变量或是函数参数,如下:

mov    0x8(%rsp),%rdx

上述汇编语言代码的指令把地址为0x8(%rsp)的内存中的值拷贝到寄存器rdx,此操作就是使用rsp寄存器加一定偏移来读取内存中的值。

到此基础的CPU寄存器相关内容聊得差不多了,这并不是需要了解的全部内容,后续文章中会有体现,喜欢本文的话,欢迎来个三连击。

扫码关注公众号,获取更多优质内容。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

聊一聊基础的CPU寄存器~ 的相关文章

随机推荐

  • 本地、服务器文件互传命令

    1 从服务器复制文件 文件夹到本地 scp r ZSL 192 168 53 54 data ZSL json D WorkSpace PyCharm myfiel 加上r可以复制整个文件夹 不加r只能复制单个文件 2 从本地复制文件夹到服
  • protocol buffer 简单使用

    protocol buffer占用空间小 传输速率高 并且是跨平台的 每个语言都有一套解释protocol buffer的特殊方式 我就介绍一下C 如何解析protocol buffer 首先我们要自己编译Protogen 地址 如下 ht
  • Synchronized 锁升级(无锁、偏向锁、轻量级锁、重量级锁)

    一概念 是Java中一个关键字 是JVM层面提供的同步锁机制 用于保证多线程访问同一资源的可见性 互斥性 即当一个线程已经获取资源锁时 其他试图获取的线程只能等待或者阻塞在那里 访问静态 synchronized 方法占用的锁是当前类的锁
  • C++标准库学习(三)--队列和string类

    今天学习了C 的queue和string类的基本操作 queue是自带的队列 应用很是方便 要注意 pop函数并不返回pop出的值 include
  • FlowUs 使用攻略:如何快速制作 Web 应用(PWA)

    最近在寻找 Notion 的替代品过程中 我发现了 FlowUs 虽然是后起之秀 但不是唯 Notion 亦步亦趋 FLowUs 有两个很重要的特性打动了我 支持文件夹页面 一直以来 虽然 Notion 等产品十分强大 试图取代 Offic
  • powershell(二)对数据库的增删改查

    数据库配置 Database 数据库名称 数据库实例名 Server localhost SQL2008 用户名 UserName sa 密码 Password 数据库密码 连接数据库 SqlConn New Object System D
  • Databend 设计概述

    Databend 是一个开源的 完全面向云架构的新式数仓 它提供快速的弹性扩展能力 并结合云的弹性 简单性和低成本 使 Data Cloud 构建变得更加容易 Databend 把数据存储在像 AWS S3 Azure Blob 这些云上的
  • Java自定义注解的使用

    注解的定义 注解是一种能被添加到java源代码中的元数据 可以看做是是一种特殊标记 可以在包 类 参数和方法上使用 可以进行一些特殊的处理 访问修饰符必须为public 不写默认为public 元注解 JDK中有一些元注解来修饰注解 主要包
  • 浏览器提示:你的连接不是专用连接的解决方法

    解决方法 1 调整键盘为英文输入状态 2 鼠标点击当前页面任意位置 然后依次按键 thisisunsafe 输入完成后 页面会自动刷新 即可正常访问
  • 基于STM32的SGP30芯片开发例程

    2021 03 10新增 附上SGP30的官方资料和STM32F103的开发例程 链接 https pan baidu com s 1pnUTTcXzY1GqiWg 6QcB5Q 提取码 92m9 复制这段内容后打开百度网盘手机App 操作
  • WordPress网站的robots文件代码怎样写比较好

    本文记载和介绍的是wordpress的robots txt的在哪儿 以及如何修改robots文件来禁止搜索引擎爬取 ajax目录下的文章 以及如何优化WordPress网站的robots文件 wordpress设置robots文件的目录 w
  • Linux编程获取本机IP地址的几种方法

    在进行Linux网络编程时 经常会需要获取本机IP地址 除了常规的读取配置文件外 本文罗列几种个人所知的编程常用方法 仅供参考 如有错误请指出 方法一 使用ioctl 获取本地IP地址 Linux下可以使用ioctl 函数以及结构体 str
  • json 插入数据_MongoDB如何一次插入多条json数据

    背景 MongoDB 是一个基于分布式文件存储的数据库 由 C 语言编写 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案 MongoDB 是一个介于关系数据库和非关系数据库之间的产品 是非关系数据库当中功能最丰富 最像关系数据库的
  • PCL RANSAC拟合空间3D椭圆

    目录 一 算法原理 1 空间椭圆 2 模型系数 3 参考文献 二 代码实现 三 结果展示 四 测试数据 一 算法原理 1 空间椭圆 椭圆的参数方程为 x t
  • 阿里云轻量服务器使用教程_3分钟建站

    阿里云轻量应用服务器怎么使用 阿里云轻量应用服务器使用教程 轻量应用服务器购买 重置密码 远程连接 宝塔面板的Web环境搭建 WordPress网站程序安装到网站上线 阿里云服务器网分享轻量应用服务器从购买 配置建站环境 轻量服务器应用服务
  • JS中的常用事件及事件注册的两种方式

  • Caused by java lang NoClassDefFoundError org/springframewo

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 http blog csdn net jiangjunshow 也欢迎大家转载本篇文章 分享知识 造福人民 实现我们中华民族伟大复兴 1 错误描述 严重 A child container
  • LNMP环境的搭建及PHP网页的发布

    目录 一 安装nginx服务 1 检查网络环境 查看服务器是否可以上网 2 Centos 7 配置阿里云 yum源和安装 EPEL源 1 对默认原文件进行备份 2 配置阿里云yum源 3 安装 EPEL源 4 安装nginx 二 安装my
  • 深度学习图像搜索与识别

    github 搜索 image retrieval 算法大合集 GitHub willard yuan awesome cbir papers Awesome and classical image retrieval papers 模型比
  • 聊一聊基础的CPU寄存器~

    寄存器 CPU内部的存储单元 用于存放从内存读取而来的数据 包括指令 和CPU运算的中间结果 使用寄存器来临时存放数据而不直接操作内存原因如下 CPU的工作原理决定了有些操作只能在CPU内部进行 CPU读写寄存器的速度比读写内存的速度要快很