2024王道考研计算机组成原理——指令系统
零、本章概要
指令寻址:解决的是PC+"1"的问题
数据寻址:使用寄存器/内存/结合
基址寻址:用于多道程序的并发执行
直接寻址:call 0x12345678
变址寻址:esi edi用于循环,因为使用直接寻址需要一堆地址很麻烦,速度也慢
相对寻址:地址针对的是相对于PC的位置,在代码位置发生改变的情况下用于实现跳转
PSW就是EFLAGS
x86汇编:
使用cmp+jnz(等)实现跳转指令;cmp会修改PSW的内容,jnz指令执行的适合会根据psw来判断需不需要跳转
循环语句:for(int i=0;i<10;i++){s+=arr[i];}:i++后面紧跟cmp
函数调用底层实现:
堆栈平衡:函数调用前后esp和ebp的位置不变,一个线程内的所有函数共用一个堆栈
x86的push和pop默认是按照4字节压栈/出栈的
esp指向的是栈顶的位置(有元素)
push eax:①先sub esp,4 ②再mov [esp],eax
pop eax:①先mov eax,[esp] ②再add esp,4
call eax:①push eip ②jmp eax
ret:pop eip(默认是ret 4)
真实的函数堆栈以及函数调用(见C语言函数调用的汇编视角)
CICS和RISC指令集的对比
一、指令格式

操作码:做什么 地址码:对谁做
当然停机指令特殊,不需要地址码,就是执行一个特殊的命令而已
Intel的CPU使用的是x86架构,x86架构的指令集和AMD的指令集是不兼容的,不能跨不同指令系统的机器执行,苹果公司宣布要抛弃Intel的CPU,转而开发自己的基于ARM架构的CPU,这样手机和电脑就能通用了

了解即可:
堆栈型计算机通过零地址指令来进行算术运算:操作数是隐藏在栈里面的,而不会显示地在栈中指明,扫描到操作符就相当于扫描到了一个零地址指令,会把操作数计算/弹出堆栈

所有指令访存次数都要加上取指令的那一次




注意:指令字长的长度是可变的(但是得是比如1B的整数倍),机器字长和存储字长都是不可变的
如果指令字长超过机器字长的话就需要多次的取指令操作,CPU可以根据操作码的类型来判断



我们所有的指令都是遵循操作码+地址码这种格式,只是地址码有可能为0,只有操作码这种情况出现,表示仅执行一次特殊的操作

二、扩展操作码指令格式
操作码全1用于区分是几地址指令
这里重点讨论的是n位操作码,能表示2^n种对于3/2/1地址的操作

三地址:15条0000-1110 A1 A2 A3
二地址(12条):1111 0000-1011 A1 A2
一地址(62条):1111 11 000000-111101 A1
零地址(32条):1111 11 11111 00000-11111
cpu分析指令的时候就根据前几位是1来判断他是几地址指令


三、指令寻址

PC+“1”
指令系统采用定长指令字结构: 定长指令+可变长操作码
因为每一条指令的长度是确定的,所以+"1"即可处理下一条指令

指令执行的时候先读入一个字
这里我想给大家重点讲解一下!!!!!!!!!!!!!!!!!!!!!!!
你CPU不是要从内存当中取指令吗?因为CPU一次最多只能同时处理一个字的数据,你就直接去指令所在的内存单元(在PC里存放地址)去取出一个字的内容,但是啊这一个字不是都有效啊!我CPU处理第一个字节的时候发现是55,后面直接扔掉就是了,然后根据55我就能知道这条指令的长度了,也就能知道PC应该加几了!然后可以继续去取下一条地址了!!!!!!!!



四、数据寻址

根据寻址特征和形式地址可以确定操作数的真实地址(EA)

了解即可,不用看:
立即寻址:立即数#010
直接寻址:call 0x12345678
间接寻址:lea [0x123456],地址放在某个内存单元里面
寄存器寻址:push ebp;mov eax,ecx
寄存器间接寻址:push [eax+4]

基址寻址就是用于多道程序并发执行的



直接寻址的bug:要用一堆地址

如何解决? esi edi就是变址寄存器,用于实现循环:rep stosw

直接寻址:地址是几就是几,你位置移动也是跳到2那里
(如何解决这个问题?)

你移动代码对顺序执行的指令没啥影响,但是跳转指令难绷啊😂😂😂
所以只要修改跳转指令的解释方式:因为PC会自动+1,所以使用-4(补码)来指示当前的CPU情况下应该跳转到哪里去执行
转移指令使用的都是相对寻址!!!

基址寻址:整个代码在内存当中的浮动;相对寻址:一段代码在程序内部的浮动

比较(相减)和跳转是分开的
PSW就是我们熟悉的ELAPGS

五、x86汇编语言基础
指令格式是什么样的取决于你的CPU,硬编码就是指令集里面的指令
55就是opcode,66就是前缀,CPU根据值来判断
55为啥是push ebp而不是push bp和当前CPU的模式有关,x86的保护模式默认是32位
前缀指令分成4个组,每个组有n个最多出现一个
定长指令:opcode确定了,指令的长度就确定了
变长指令:即使opcode确定了,指令的长度依然无法确定
opcode决定了有没有ModR/M,也决定了是不是定长指令
比如opcode是88那它后面一定根一个opcode


地址偏移和立即数

比如这种考题:

为啥x86汇编语言不允许两个操作数都同时来自主存?
1、指令长度太长了
2、访问2次主存太慢了吧。。。



x86:intel的8086/80286 80386
一条指令由操作码和若干地址码组成

进行除法运算的时候要对被除数进行位扩展:32->64(edx:eax) ,商存入eax,余数存入edx


intel格式(Windows)&AT&T(Linux&Unix)格式(汇编格式)


六、C语言选择语句的汇编实现
在x86当中IP就是PC
和前面提到的一样,我们这样写汇编代码,但是其实最后变成机器码的时候他会给我们翻译成与PC有关的指令,这样代码段即使移动位置,当PC指向这条语句的时候也能够跳转到正确的地址(使用PC+一个补码)

使用标号可以更方便程序员去编写汇编代码,最后编译器要做的就是把这个标号改成对于的地址

条件转移指令通常与cmp指令配合食用🤣🤣🤣

switch语句:离散情况不生成大表和if...else效率一样,连续的时候生成大表,先比较数值-1超过第二大的数就直接跳到default,否则直接根据edx*4+func(函数首地址) 来去查大表,直接得到跳转地址而不用像if..else那样进行多次的比较!!!
只有特定的指令(比如运算指令,和ALU有关,本质上不就是加法器那些产生的符号位吗?)才会修改PSW寄存器里面的标志位,cmp指令本质上就是做了一个减法(但是结果不保存,只改变符号位),产生了符号位,然后条件转移指令再根据减法所产生的标志位(去PSW寄存器中获取)来决定要不要进行跳转!!!

六、C语言循环语句的汇编实现
i++后面紧跟的就是cmp,一旦越界就跳出循环
for:①先初始化,第一次直接判断是否跳出循环
②循环主体&i++③cmp i ,cnt(没结束就往上跳是for循环的一大重要特征!)

七、C语言函数调用的汇编视角


x86的push和pop默认是按照4字节压栈/出栈的
esp指向的是栈顶的位置(有元素)
push eax:①先sub esp,4 ②再mov [esp],eax
pop eax:①先mov eax,[esp] ②再add esp,4
call eax:①push eip ②jmp eax
ret:pop eip(默认是ret 4)


真实的堆栈以及函数调用:

所谓堆栈平衡就是函数调用前和调用后esp和ebp的位置保持不变!


试试看能不能画到堆栈平衡?
外平栈(默认采用的调用约定):cdcall(右左,外平栈:add esp,8)
内平栈:stdcall(右左,内平栈:ret 8(相当于add esp,8))

注意:一个线程里面的所有函数都使用同一个堆栈
int main(){
fun(2,3); push 3 push 2 call fun(push eip + jmp fun)
}
fun:

八、CICS和RISC指令集的对比


你RISC只能通过寄存器来访存,寄存器可不得比CICS多吗?

相关文章:
2024王道考研计算机组成原理——指令系统
零、本章概要 指令寻址:解决的是PC"1"的问题 数据寻址:使用寄存器/内存/结合 基址寻址:用于多道程序的并发执行 直接寻址:call 0x12345678 变址寻址:esi edi用于循环,因为使用直接寻址需要一堆…...
vscode中如何将cmd设置为默认终端
vscode中如何将cmd设置为默认终端?下面本篇文章给大家介绍一下vscode中设置默认终端为cmdPowerShelWSL等的方法,希望对需要的朋友有所协助! 一、快捷键(CtrlShiftP打开命令面板,输入select选择“SelectDefaultProfil …...
Unity UGUI 循环滑动列表实现思路及简单代码实现
前言: 自己之前其实比着书上实现过一个循环滑动列表,并且商业化到了项目里,上线后也在用。可后来怎么也想不起来细节,看着之前的代码也看不很懂。这次复习一下,希望真能理解它的本质,也记录一下࿰…...
贪心算法(1)--经典贪心算法
目录 一、活动安排问题 二、最优装载问题 三、分数背包问题 四、多机调度问题 一、活动安排问题 1、策略 活动安排问题:设有n个活动的集合E{1,2,...,n},每个活动i都有一个使用该资源的起始时间和一个结束时间,且。如果选择了活动i则它在…...
Nginx负载均衡和备份和故障转移
如果你想要两台 Nginx 服务器配置访问同一个链接,通常意味着你可能想要以下几种配置: 负载均衡:两台 Nginx 服务器都工作,当访问者请求资源时,流量会在这两台服务器之间进行均衡分配。备份和故障转移:其中…...
Android-Framework 三方应用默认权限都不弹窗
代码位置:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java -1853,10 1853,10 public class PackageManagerService extends IPackageManager.StubmPermissionCallback);}- final String packageName res.pkg.application…...
TX Text Control.NET For WPF 32.0 Crack
TX Text Control 支持VISUAL STUDIO 2022、.NET 5 和 .NET 6 支持 .NET WPF 应用程序的文档处理 将文档编辑、创建和 PDF 生成添加到您的 WPF 应用程序中。 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款完全可编程的丰富编辑控件,它在专为 Visual Stu…...
使用Go语言测试Redis性能
1. 前言 Redis是一个高性能的键值存储数据库,常用于缓存、队列、排行榜等场景。在实际应用中,我们需要对Redis的性能进行测试,以便了解其在不同场景下的表现。本文将介绍如何使用Go语言测试Redis的性能。 2. 环境准备 在开始测试前&#x…...
【Javascript】运算符(赋值,算术,自增,自减)
目录 赋值 算术 单个变量: 多个变量: 在字符串,数组中充当连接符 自符串与字符串 数组与数组 数组与字符串 自增与自减 前置 自增 自减 后置 自增 自减 赋值 var a 1;算术 单个变量: var a 1;a 1;console.l…...
Redis数据类型——list类型数据的扩展操作
1.list阻塞式数据获取 2.list类型数据业务场景...
[论文笔记]NEZHA
引言 今天带来华为诺亚方舟实验室提出的论文NEZHA,题目是 针对中文中文语言理解神经网络上下文表示(NEural contextualiZed representation for CHinese lAnguage understanding),为了拼出哪吒。 预训练语言模型由于具有通过对大型语料库进行预训练来捕获文本中深层上下文信…...
【Linux】认识协议
目录 一、应用层二、协议三、序列化和反序列化 一、应用层 之前的socket编程,都是在通过系统调用层面,如今我们来向上打通计算机网络。认识应用层的协议和序列化与反序列化 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应…...
Hadoop3教程(三十四):(生产调优篇)MapReduce生产经验汇总
文章目录 (164)MR跑得慢的原因(165)MR常用调优参数Map阶段Reduce阶段 (166)MR数据倾斜问题参考文献 (164)MR跑得慢的原因 MR程序执行效率的瓶颈,或者说当你觉得你的MR程…...
Unity⭐️Win和Mac安卓打包环境配置
文章目录 🟥 配置Android SDK1️⃣ 配置 SDK Platforms2️⃣ 配置 SDK Tools🎁 Android SDK Build-Tools🎁 Android SDK Command-line Tools(latest)🎁 Android SDK Tools(Obsolete)🟧 配置NDK🟩 配置JDK前情提示: 此方法适用于Windows/Mac 在配置时注意开启 🪜 …...
STM32F4XX之串口
一、标准串口(UART)介绍 1、通信协议相关概念 1.1同步通信和异步通信 (1)同步通信:两个器件之间共用一个时钟线,要发送的数据在时钟的作用下一位一位发送出去。 (2)异步通信:指两个器件之间没…...
【J-Long Group Limited】申请1500万美元纳斯达克IPO上市
来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,总部位于中国香港的J-Long Group Limited(简称:J-Long)近期已向美国证券交易委员会(SEC)提交招股书,申请在纳斯达克IPO上市&…...
上传文件到google drive
参考:使用 Python 将文件上传到 Google 云端硬盘_迹忆客 第 1 步:Google API Playground 我们可以通过搜索 Google 找到更多关于 Google API Playground 的信息。 我们必须单击第一个链接才能继续前进。 选择第一个链接后,我们会自动进入下一…...
用VLOOKUP快速合并两个表格
一、前言 上周五微信收到运营提过来的需求,第一句话:帮我提取一下1号门店的库存数据,马上登录系统下载一份库存数据给到他然后专心读代码,过一会微信第二句话:帮我提取一下1号门店商品半年/一年的销量数据,…...
Vue ref属性
Vue中的ref属性可以用来对HTML元素或者是对组件进行唯一标识。 一、设置ref属性 只需要在元素或者是组件后跟上如下语法即可: ref"标识名" 二、获取元素或对象 我们可以用如下方法获取我们设置ref的元素或组件: this.$refs.标识名 第一个输…...
【python入门】函数,类和对象
【大家好,我是爱干饭的猿,本文重点介绍python入门的函数,高阶函数,python中的类和对象,模块的作用等。 后续会继续分享其他重要知识点总结,如果喜欢这篇文章,点个赞👍,关…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
