《计算机组成与设计:硬件软件接口》第二章:指令集-阅读笔记

2.1总述

--1.所选指令集来自经典指令集MIPS

2.2计算机硬件的操作

        --毫无疑必须有执行基本算数运算的指令。------冯-诺依曼

指令:add a. b. c ---知道计算机将两个变量b和c相加,并把它们的和放在a中。

-每条MIPS算数运算指令仅仅执行一个操作,并且有且只有三个操作数。

例如:将b、c、d、e的值的和放在变量a中

--add a, b, c

--add a, a, d

--add a, a, e

硬件设计四基本原则的第一个原则:1.简单源自规整

两个基本算数运算的规则:

--加:add a, b, c

--减:sub a, b, c

2.3计算机硬件的操作数

与高级语言程序不同,算术运算指令的操作数是受限制的,它们必须直接取自寄存器;寄存器数量有限,内建于硬件的特殊位置。寄存器是计算机构成的基本元素:寄存器是硬件设计中最基本的元素,在计算机设计完成以后,对程序员来说仍然是可见的。MIPS系统结构中寄存器为32位;成组的32位数由于经常出现在MIPS系统结构中,所以专门有个名字,叫做字。

高级语言的变量和寄存器的主要区别是寄存器的数量有限。现在,典型的计算机中有32个寄存器。MIPS也有32个寄存器。

本节限制条件:MIPS算术运算指令的三个操作数必须从32个32位寄存器中选取。

设计原则2:越少越快

因为电信号传输距离越远,其传输时间就越长。因此,寄存器太多将会延长时钟周期。“越少越快”

的原则并不是绝对的;寄存器个数位31的机器,其速度不一定比寄存器个数为32的机器快。在这种情况下,设计者们必须在提供更多寄存器和缩短时钟周期之间权衡。MIPS约定:用一个“$”符后面跟两个字符来代表寄存器。现在,我们将使用$s0,$s1,$s2...来代表寄存器,以对应java和c程序中的变量;用$t0,$t1,$t2...来代表将程序编译为MIPS指令时所需的临时寄存器。

2.3.1 存储器操作数

        计算机怎样来表示和访问这样复杂的数据结构?

        回顾一下计算机的五个组成部分。处理器只能将少量数据保存在寄存器中,但存储器之间有上百万的数据单元。这样,像数组这样的数据结构,将只能放在存储器中。

        正如上面所说,MIPS指令中的算数运算操作只作用于寄存器;因此,MIPS必须有在存储器和寄存器直接按你传送数据的指令,这些指令叫做数据传送指令。为了访问存储器的一个字,指令必须给出相应的存储器地址。存储器好比一个很大的一维数组,其地址相当于数组的下标,该坐标从0开始。

        把数据从存储器复制到寄存器的数据传送指令,通常叫做取指令。取指令的格式:操作符名称后面紧跟存放数据代取的寄存器,然后是用来访问存储器的常数和一个寄存器。指令的常数部分和第二个寄存器中的内容相加即得存储器地址。实际的MIPS取指令的名字为lw,表示取字(load word).

       例: 将A[8] 传送到寄存器。这个数组元素的地址由存放在$s3中的数组A的基址加上元素序号8得到。这个数据应该放在一个临时寄存器中以便在下一条指令中使用。第一条编译后的生成的指令为:

        lw $t0,8($s3)  #数组的基址存放在$s3中。

        例:将h(放在寄存器$s2中)加上A[8](放在寄存器$t0中),并将结果放到对应于g的寄存器$s1中:

        add $s1,$s2,$t0

                数据传送指令中的常量叫做偏移量(offset),存放基址的寄存器叫做基址寄存器。

MIPS的字的起始地址必须是4的倍数。这叫对齐限制,许多系统结构都有这样的限制(第五章阐明了为什么地址对齐能使数据传送加快)。

有两种字节寻址的机器:一种使用最左端或“大端”字节的地址作为字地址;另一种使用最右端或“小端”字节的地址作为字地址。MIPS采用大端编址。字节寻址也影响到数组下标。在上面的代码中,为了得到正确的字节地址,加到基址寄存器$s3的偏移量必须是4*8。

与取指令相反的指令叫做存储指令;它将数据从寄存器传送到存储器。存储指令的格式和取指令相似:操作符名称,接着是包含着待存储数据的寄存器,然后是选择数组元素的偏移量,最后是基址寄存器。同样,MIPS地址由常数和基址寄存器内容共同决定。实际的MIPS存储指令的名字为sw, 表示存储字(store word)。

例:假设变量h放在寄存器$s2中,数组A的基址放在$s3中则:A[12] = h + A[8]的MIPS汇编代码是什么样的呢?

解:

        lw $t0, 32($s3)

        add $t0,$s2,$t0

        sw  $t0,48($s3)

2.3.2常数或者立即数操作数

        许多时候一个程序 会在一个操作中使用常量--举例来说,给一个数组的下标加1以指向下一个数组元素。许多程序的变量个数要比机器的寄存器个数多得多。因此,通过使用存取指令在寄存器和存储器之间传送变量,编译器会尽量将最常用的变量保存在寄存器中而将其他的变量保存在存储器中。将不常使用的变量存放在存储器中的这个过程叫做寄存器换出。

        根据硬件设计原则--大小和速度的关系是越小越快,存储器一定比寄存器慢--因为寄存器更小。另外,寄存器的数据用处更大。一条MIPS算数运算指令一次能够读两个寄存器,对它们进行运算,并写入运算结果。MIPS中一条数据传送指令一次只能读一个操作数或写一个操作数,并且不能对它们进行运算。因此,MIPS中寄存器与存储器相比,不仅访问时间短,而且吞吐率高。这是一种极难得的组合,使得寄存器中的数据访问速度快,且易于使用。为了获得最高的性能,MIPS编译器必须有效地使用寄存器。

设计原则3:加速执行常用操作。

有常数操作数的快速加指令叫做立即数加,挥着写作addi。

例: addi   $s3, $s3, 4

2.4计算机中指令的表示

人们使用计算机指令的方式与计算机执行这些指令的方式是不同的。数字以一系列高、低电平信号的形式保存在计算机硬件中,因此使用二进制编码来表示。指令也以一系列高低电平信号形式保存在计算机中,并以数字形式表示。实际上,每条指令的各个部分可以看作单个的数字,将这些数字拼在一起就形成了指令。因为几乎所有的指令都用到了寄存器,所以必须规定如何将寄存器名字映射成对应的寄存器序号。MIPS汇编语言中,寄存器$s0~$s7分别对应寄存器16~23,同时,寄存器$t0~$t7分别对应寄存器8~15.

例:给出MIPS指令:add $t0, $sq, $s2的十进制数表示形式,接着给出其二进制数表示形式。

解:十进制表示为:0  17  18  8   0  32

#一条指令的每一段叫做一个字段。第一个字段和最后一个字段(0和32)组合起来告诉MIPS计算机这条指令执行加法运算。第二个字段表示加法操作的第一个源操作数寄存器号(17 = $s1),第三个字段表示加法操作的另一个源操作数寄存器号(18 = $s2)。第四个字段中存放目的操作数寄存器号(8 = $t0)。第五个字段在这条指令中没用用到。这样,这条指令将寄存器$s1和$s2的内容相加,并将结果(和)存放在寄存器$t0中。

该指令的二进制字段表示为:

000000   10001 10010  01000  00000 100000

6位            5位    5位       5位       5位      6位

为了将它与汇编语言指令区分开,把指令的数字形式称为机器语言,这样的指令序列叫做机器代码。指令的这种设计叫做指令格式。可以看出,上述MIPS指令刚好32位--与数据字长度一样。为了遵循“简单源自规整”的设计原则,所有的MIPS指令都是32位长。由于几乎所有的计算机的数据大小都是4的整数倍,因此十六进制的数很是流行。为了避免混淆,我们在这约定,给十进制数加下标ten,给十六进制加下标hex,给二进制数加下标two。BTW,C和java中用符号Oxnnnn来表示十六进制数。

MIPS字段:

给MIPS字段命名以使讨论更为简单:

        op    rs    rt   rd  shamt   funct

MIPS指令各个字段的含义如下:

 --op: 指令的基本操作,通常称为操作码

 --rs: 第一个源操作数寄存器

 --rt:第二个源操作数寄存器

 --rd: 存放操作结果的目的操作数寄存器

 --shamt:  位移量。

 --funct: 函数。这个字段选择字段op中操作码的各种特定的变体,有时叫做函数码。

设计原则4:优秀的设计需要适当的折中。

MIPS的折中方案:所有的指令长度相同,但不同的指令采用不同的指令格式。例如,上述格式叫做R型(寄存器)。另一种指令格式叫做I型(立即数)。

I型: op  rs  rt  constant or address(16位).

不同的指令格式由第一个字段的值来区分:每种格式的第一个字段(op)都被分配了一套不同的值,因此计算机硬件可以根据op来确定指令的后半部分是那种类型。

2.5逻辑运算

一些指令被加进来以使那些需要打包或者拆包位的事情简单化。这些指令就是逻辑操作。

一些逻辑操作(C操作符):

 左移:<<  右移:>>  按位与:& 按位或:| 按位非:~

第一类指令被称为移位(shift)指令。它们将一个字里面的所有位都往右或者往左移,并在空出来的位上填充0。

左移和右移的MIPS移位指令的确切名字是:逻辑左移(sll)和逻辑右移(srl)。

例:sll $t2, $s0, 4 #将$s0中的元素左移四位,然后将新元素存入$t2中。

R型指令中的shamt字段,它在移位指令中用作移位量。

sll 解码之后 op字段和funct字段都是0,rd包含$t2, rt包含$s0,shamt包含4.

按位与操作:and  $t0, $t1, $t2 .#将$t1 和$t2按位与,所得结果存入$t0中。

如你所见,当源操作数位模式的某位为0时,AND可以设置目标数对应位为0.这种和AND联合使用的位模式习惯上被称为掩码,因为掩码"隐藏"了某些位。

按位或操作(MIPS指令):or $t0, $t1, $t2  #reg $t0 -reg $t1 | $t2

取反操作有些特别。为了保持双操作数的格式,MIPS的设计者决定引入指令或非(NOT OR)来取代(OR)。而将或非操作的一个操作数设为0则其就等同于NOT.

例:A NOR 0 = NOT(A OR 0) = NOT(A)。

将寄存器$t3中的值设为0,则NOT的MIPS指令为:

        nor $t0, $t1, $t3

像在算术运算中一样,常数在AND和OR这些逻辑运算里4也是很有用的,因此MIPS也提供了

and immediate(andi)(立即数与)和or immediate(ori)(立即数或)指令

<think>好的,用户遇到了Git合并时本地更改会被覆盖的问题,需要解决方案。根据之前的引用资料,解决方法主要有commit、stash和revert三种。首先,我得确认用户的具体情况,比如他们的本地更改是否已经完成,是否需要保留,或者是否可以丢弃。用户可能不太清楚这三种方法的适用场景,需要详细解释每个选项的步骤和优缺点。比如,commit适用于需要保留更改的情况,stash适合临时保存以便后续恢复,而revert则是直接撤销更改,适用于不需要保留的情况。需要结构清晰,分点说明,每个方法都给出操作步骤和适用场景,帮助用户理解哪种情况最适合他们。还要注意使用中文,避免技术术语过于复杂,让用户容易理解。同时,生成相关问题,可能涉及如何恢复stash的内容,或者如何避免频繁冲突等,扩展用户的知识点。另外,要确保LaTeX格式正确,但在这个问题中可能用不上数学公式,所以主要关注代码块和引用标识。检查引用是否正确,比如引用[^1]和[^2]的来源是否相关,用户提供的引用内容是否准确对应解决方案。 最后,确保回答真实可靠,操作步骤准确无误,避免误导用户。可能还需要提醒用户根据具体情况选择方法,比如如果有未完成的实验性代码,stash可能是更好的选择,而如果是确定要保留的修改,则应该commit。</think>要解决Git合并时本地更改被覆盖的问题,可根据不同场景选择以下三种方法: ### 一、提交本地更改(commit) **适用场景**:当本地更改已测试通过且需要保留到版本历史中。 **操作步骤**: 1. 将改动添加到暂存区: ```bash git add . # 添加所有文件 # 或指定文件 git add file1.txt file2.py ``` 2. 提交更改并添加描述: ```bash git commit -m "完成用户登录模块优化" ``` 3. 执行合并操作: ```bash git merge origin/main ``` **优点**:保留完整的开发记录,便于后续追溯[^1]。 ### 二、暂存更改(stash) **适用场景**:需要临时保存未完成的修改(如调试代码),优先处理合并操作。 **操作步骤**: 1. 保存当前工作状态: ```bash git stash # 可选添加备注 git stash save "用户登录模块调试代码" ``` 2. 查看暂存记录列表: ```bash git stash list ``` 3. 合并远程分支: ```bash git merge origin/main ``` 4. 恢复暂存内容: ```bash git stash pop # 恢复并删除最近一次暂存 # 或指定特定暂存 git stash apply stash@{1} ``` **优点**:保持工作目录整洁,特别适合处理紧急合并任务[^2]。 ### 三、撤销本地更改(revert) **适用场景**:本地修改可丢弃(如实验性代码或错误修改)。 **操作步骤**: 1. 撤销所有未提交的修改: ```bash git checkout -- . # 全部文件 # 或指定文件 git checkout -- file1.txt ``` 2. 执行合并操作: ```bash git merge origin/main ``` **风险提示**:此操作不可逆,需确认文件无需保留。 --- ### 对比决策表 | 方法 | 保留记录 | 可恢复性 | 适用阶段 | |---------|----------|----------|------------------| | commit | ✅ | ✅ | 功能开发完成时 | | stash | ❌ | ✅ | 开发中途临时切换 | | revert | ❌ | ❌ | 放弃无效修改 | ### 扩展应用场景 - 当存在多个暂存时,可用`git stash list`查看记录,通过`git stash apply stash@{n}`精准恢复 - 合并后出现冲突时,可使用`git mergetool`可视化工具解决冲突 - 长期分支开发推荐使用`git rebase`保持提交历史线性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值