当前位置: 首页 > news >正文

高级编程语言的基本语法在CPU的眼中是什么样的呢?

任何一门高级编程语言,就一定存在下面这几个语法元素

  1. 变量
  2. 类型
  3. 数组
  4. 控制语句(条件,循环)
  5. 运算符(算术运算,布尔运算,赋值运算,关系运算,位运算)
  6. 函数

而本节探究的是,这6个语法元素在CPU的眼中是什么样子的呢?我们先来看看变量。

说到变量我们的先从内存说起,为了方便管理,整个内存被划分为一块一块的,我们把这样一块的内存叫做内存单元,通常情况下,一块内存单元的大小为一个字节,我们需要给这些内存单元编号,从0开始,而这个编号有个专门的名字,叫做内存地址。CPU比较偏爱内存地址,因为知道内存地址就可以操作对应的内存单元。但是我们并不喜欢内存地址,因为内存地址是一串数字,没有任何可读性,于是我们映入变量的概念,变量就是这块内存单元的别名。一个比较合适的类比:变量与内存地址的关系和域名与IP地址的关系一样。比如下面这两段代码

#include <stdio.h>
int main() {int a = 1;return 0;
}
main:push    rbpmov     rbp, rspmov     DWORD PTR [rbp-4], 1 ; 这里就是 int a = 1;mov     eax, 0pop     rbpret

接下来我们来谈谈类型,类似其实有两个作用,对于我们开发者而言,必要的类型检验可以帮我我们减少代码错误。对于CPU而言,类型指定了操作数的大小。比如下面这两段代码:

#include <stdio.h>
int main() {int num1 = 1;long num2 = 100;return 0;
}
main:push    rbpmov     rbp, rspmov     DWORD PTR [rbp-4], 1 ; int num1 = 1;mov     QWORD PTR [rbp-16], 100 ; long num2 = 100;mov     eax, 0pop     rbpret

DWORD 表示操作4个内存单元,QWORD 表示操作8个内存单元

基本上每个编程语言都提供了数组这个基础的数据结构,为什么呢?因为现实世界需要,因为有这样的需求。通常意义上,数组是存储多个同类型的数据结构,这意味这他的内存结构是连续的。所以对于CPU而言,他不过是一块连续的内存单元而已。

控制语句可以说是编程语言的灵魂,全部的程序都是由条件语句,循环语句这样像搭积木一样搭建出来的。而这些控制语句在CPU的眼中,不过是几条固定的指令。

#include <stdio.h>int main() {int a = 10;int b = 9;if (a > b) {printf("a more than b");}else {printf("b more than a");}
}
.LC0:.string "a more than b"
.LC1:.string "b more than a"
main:push    rbpmov     rbp, rspsub     rsp, 16mov     DWORD PTR [rbp-4], 10mov     DWORD PTR [rbp-8], 9mov     eax, DWORD PTR [rbp-4]cmp     eax, DWORD PTR [rbp-8]jle     .L2mov     edi, OFFSET FLAT:.LC0mov     eax, 0call    printfjmp     .L3
.L2:mov     edi, OFFSET FLAT:.LC1mov     eax, 0call    printf
.L3:mov     eax, 0leaveret

可以发现控制语句对应的指令就是 jxx 循环语句也是一样的,只不过不是跳转的位置不是往后,而是往前。

#include <stdio.h>int main() {int sum = 0;for (int i = 0; i<= 100; i++) {sum += i;}
}
main:push    rbpmov     rbp, rspmov     DWORD PTR [rbp-4], 0mov     DWORD PTR [rbp-8], 0jmp     .L2
.L3:mov     eax, DWORD PTR [rbp-8]add     DWORD PTR [rbp-4], eax ; sum += i;add     DWORD PTR [rbp-8], 1 ; i++
.L2:cmp     DWORD PTR [rbp-8], 100 ; i <= 100;jle     .L3mov     eax, 0pop     rbpret

高级语言中的运算符就更加不用说了,不过是一些运算指令。到此编写一个程序所需要的全部语法在CPU层面都已经解构完毕了,而函数不过是一种让程序模块化的最基本的手段。方便我们在编写庞大,复杂的程序时,能够更加简单,更加灵活。那么函数在CPU的眼中是什么样子的呢?

函数的出现,让变量的生命周期(也叫作用域)有了区别,函数内部的变量会随着函数的调用而创建,函数的返回而销毁。这样做的目的是充分利用内存。接下来我们通过一个例子来看看函数是如何被调用的,又是如何被返回的。

#include <stdio.h>int f1(int num) {int max = 100;return num + max;
}int main() {int init = 10;int res = f1(init);return 0;
}
f1:push    rbpmov     rbp, rspmov     DWORD PTR [rbp-20], edimov     DWORD PTR [rbp-4], 100mov     edx, DWORD PTR [rbp-20]mov     eax, DWORD PTR [rbp-4]add     eax, edxpop     rbpret
main:push    rbpmov     rbp, rspsub     rsp, 16mov     DWORD PTR [rbp-4], 10mov     eax, DWORD PTR [rbp-4]mov     edi, eaxcall    f1mov     DWORD PTR [rbp-8], eaxmov     eax, 0leaveret

可以发现,调用函数会使用call指令,这个指令的作用是将下一条的指令入栈,然后跳转到f1代码段,在每个函数的开头都有这两行指令,push rbp mov rbp, rsp 这两条指令的作用是,先保存上一个函数的栈帧起点,然后重置栈帧的起点为当前的栈顶,即创建一个新的栈帧。然后再存放局部变量。然后函数结束,pop rbp ret 执行这两条指令,rbp寄存器回到上一个函数的栈帧的起点,ret指令让指令寄存器IP,回到调用函数的位置继续执行。

到此,相信你一定有所体会,CPU很呆板,只会按照我们写好的指令一条一条的执行。我们可以看到比较高级的语法,例如函数调用其实不是CPU本身就支持,而是我们通过一些额外的指令让CPU可以做到函数调用,而这些额外的指令都是编译器生成的。所以我们常常说一个语言是否支持某种语言特性,取决于它的编译器

相关文章:

高级编程语言的基本语法在CPU的眼中是什么样的呢?

任何一门高级编程语言&#xff0c;就一定存在下面这几个语法元素 变量类型数组控制语句&#xff08;条件&#xff0c;循环&#xff09;运算符&#xff08;算术运算&#xff0c;布尔运算&#xff0c;赋值运算&#xff0c;关系运算&#xff0c;位运算&#xff09;函数 而本节探…...

Redis 性能优化:多维度技术解析与实战策略

文章目录 1 基准性能2 使用 slowlog 优化耗时命令3 big key 优化4 使用 lazy free 特性5 缩短键值对的存储长度6 设置键值的过期时间7 禁用耗时长的查询命令8 使用 Pipeline 批量操作数据9 避免大量数据同时失效10 客户端使用优化11 限制 Redis 内存大小12 使用物理机而非虚拟机…...

.netframwork模拟启动webapi服务并编写对应api接口

在.NET Framework环境中模拟启动Web服务&#xff0c;可以使用几种不同的方法。一个常见的选择是利用HttpListener类来创建一个简单的HTTP服务器&#xff0c;或者使用Owin/Katana库来自托管ASP.NET Web API或MVC应用。下面简要介绍Owin/Katana示例代码。这种方法更加灵活&#x…...

MongoDB 学习指南与资料分享

MongoDB学习资料 MongoDB学习资料 MongoDB学习资料 在数据爆炸的当下&#xff0c;MongoDB 作为非关系型数据库的佼佼者&#xff0c;以其独特优势在各领域发光发热。无论是海量数据的存储&#xff0c;还是复杂数据结构的处理&#xff0c;MongoDB 都能轻松应对。接下来&#xf…...

【Azure 架构师学习笔记】- Azure Function (2) --实操1

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Function 】系列。 接上文【Azure 架构师学习笔记】- Azure Function (1) --环境搭建和背景介绍 前言 上一文介绍了环境搭建&#xff0c;接下来就在本地环境下使用一下。 环境准备 这里我下载了最新的VS studio&…...

扫描深度?滤光片和偏振片区别?

扫描深度 https://www.shining3d.cn/chike/kousao/aoralscan-wireless.html 是指扫描仪能够准确捕捉和测量的最大距离范围。这一参数对于不同类型的三维扫描仪和应用场景非常重要&#xff0c;具体含义包括&#xff1a; 扫描范围 定义: 扫描深度通常指从扫描仪到被扫描物体表…...

HJ4 字符串分隔(Java版)

一、试题地址 字符串分隔_牛客题霸_牛客网 二、试题内容 描述 对于给定的由小写字母和数字混合构成的字符串 s &#xff0c;你需要按每 8 个字符换一行的方式书写它&#xff0c;具体地&#xff1a; 书写前 8 个字符&#xff0c;换行&#xff1b;书写接下来的 88 个字符&am…...

【脑机接口数据处理】matlab读取ns6 NS6 ns5NS5格式脑电数据

文章目录 MATLAB函数openNSx详解&#xff1a;轻松读取NSx文件函数概述下载文件基本用法注意事项示例 结论 MATLAB函数openNSx详解&#xff1a;轻松读取NSx文件 在神经科学和生物医学工程领域&#xff0c;处理神经信号数据是一项常见且重要的任务。NSx文件格式是一种用于存储神…...

用C++实现一个基于模板的观察者设计模式

观察者模式 定义 观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系,使得当一个对象状态发生变化时,其所有依赖它的对象都会收到通知并自动更新。 核心概念 角色定义 Subject(被观察者): 持有观察者列表,维护观察者的注册和移除。 …...

【华为路由/交换机的ftp文件操作】

华为路由/交换机的ftp文件操作 PC&#xff1a;10.0.1.1 R1&#xff1a;10.0.1.254 / 10.0.2.254 FTP&#xff1a;10.0.2.1 S1&#xff1a;无配置 在桌面创建FTP-Huawei文件夹&#xff0c;里面创建config/test.txt。 点击上图中的“启动”按钮。 然后ftp到server&#xff0c;…...

微信小程序 实现拼图功能

微信小程序 实现拼图 效果示例功能描述代码示例 效果示例 微信小程序 碎片拼图 功能描述 在微信小程序中&#xff0c;实现一个简单的拼图小游戏。用户需要将四张碎片图片拖动到目标图片的正确位置&#xff0c;具体功能如下&#xff1a; 拖动功能&#xff1a; 用户可以通过手指…...

深度学习项目--基于LSTM的火灾预测研究(pytorch实现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 LSTM模型一直是一个很经典的模型&#xff0c;这个模型当然也很复杂&#xff0c;一般需要先学习RNN、GRU模型之后再学&#xff0c;GRU、LSTM的模型讲解将…...

AI时代下 | 通义灵码冲刺备战求职季

AI时代下 | 通义灵码冲刺备战求职季 什么是通义灵码使用智能编程助手备战求职靠谱吗体验心得 AI时代下&#xff0c;备战求职季有了不一样的方法&#xff0c;使用通义灵码冲刺备战求职季&#xff0c;会有什么样的体验&#xff1f; 什么是通义灵码 在开始话题之前&#xff0c;首…...

当comfyui-reactor-node 安装失败urllib.error.HTTPError: HTTP Error 403: Forbidden解决方法

comfyUI 节点comfyui-reactor-node 安装 python install 时 报错 urllib.error.HTTPError: HTTP Error 403: Forbidden 如下&#xff1a; (xxx) xxxxxxx:~/sdb/Q/ComfyUI/custom_nodes/comfyui-reactor-node$ python install.py Traceback (most recent call last): File …...

SSE 实践:用 Vue 和 Spring Boot 实现实时数据传输

前言 大家好&#xff0c;我是雪荷。最近我在灵犀 BI 项目中引入了 SSE 技术&#xff0c;以保证图表的实时渲染&#xff0c;当图表渲染完毕服务端推送消息至浏览器端触发重新渲染。 什么是 SSE&#xff1f; SSE 全称为 Server-Send Events 意思是服务端推送事件。 SSE 相比于 …...

TouchGFX学习笔记(一)

配置请参考链接&#xff1a;TouchGFX超低配置移植教程-CSDN博客 一&#xff0c;显示配置 1.适当增加堆栈大小 2.适当增大缓冲大小 双重缓冲消除了任何撕裂的风险&#xff0c;无论渲染下一帧需要多长时间&#xff0c;因为TfT控制器&#xff0c;例如&#xff0c;总是可以访问最…...

Java算法 二叉树入门 力扣简单题相同的树 翻转二叉树 判断对称二叉树 递归求二叉树的层数

目录 模版 先序遍历 中序遍历 后序遍历 力扣原题 相同的二叉树 力扣原题 翻转二叉树 遍历树的层数 题目 静态变量 核心逻辑 模版 // 二叉树public static class Node{public int value;public Node left;public Node right;public Node(int v) {valuev;}} 先序遍历 …...

如何将 session 共享存储到 redis 中

文章目录 一. 分布式 session 登录1.1 什么是分布式&#xff1f;1.2 Session 共享1.3 为什么服务器 A 登录后&#xff0c;请求发到服务器 B&#xff0c;不认识该用户&#xff1f;1.4 共享存储 二. Session 共享实现Redis三. 测试session共享四. cookie设置4.1 前端4.2 后端 一.…...

vue3学习三

五 计算属性 定义 选项式 export default {data(){return {num:1}},computed:{num1(){this.num1}} } 组合式 import {ref,computed} from vuelet numref(0); //仅读 let num1 computed(()>{return num.value1 }) 计算时依赖的变量数据发生变化&#xff0c;则计算属性…...

彻底理解JVM类加载机制

文章目录 一、类加载器和双亲委派机制1.1、类加载器1.2、双亲委派机制1.3、自定义类加载器1.4、打破双亲委派机制 二、类的加载 图片来源&#xff1a;图灵学院   由上图可知&#xff0c;创建对象&#xff0c;执行其中的方法&#xff0c;在java层面&#xff0c;最重要的有获取…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

文件上传漏洞防御全攻略

要全面防范文件上传漏洞&#xff0c;需构建多层防御体系&#xff0c;结合技术验证、存储隔离与权限控制&#xff1a; &#x1f512; 一、基础防护层 前端校验&#xff08;仅辅助&#xff09; 通过JavaScript限制文件后缀名&#xff08;白名单&#xff09;和大小&#xff0c;提…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...

【Pandas】pandas DataFrame dropna

Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值&#xff08;NaN&#xff09;DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充&#xff08;即“下一个有效观测值”&#xff09…...

多模态学习路线(2)——DL基础系列

目录 前言 一、归一化 1. Layer Normalization (LN) 2. Batch Normalization (BN) 3. Instance Normalization (IN) 4. Group Normalization (GN) 5. Root Mean Square Normalization&#xff08;RMSNorm&#xff09; 二、激活函数 1. Sigmoid激活函数&#xff08;二分类&…...