910 likes | 1.27k Views
计算机组成与结构. 第二章 计算机指令 张锦. 2.1 概述. 控制计算机工作必须使用其能理解的“语言” 机器语言的单词 - 指令,单词表 - 指令集 指令集:一个给定的体系结构所能理解的命令集合 所有的机器语言都非常类似 构成计算机的硬件技术基于相似的底层原理 一些基本操作是所有计算机都必须提供的 计算机设计者具有共同的目标: 以最低的成本得到最好的性能 设计一种使硬件设计和编译器构造更简洁的语言. 2.1 概述. “设备简单性”是应当着重考虑的问题 本章将描述一个遵循该思路的指令集,并展示如何用硬件描述,以及其和高级语言的关系
E N D
计算机组成与结构 第二章 计算机指令 张锦
2.1 概述 • 控制计算机工作必须使用其能理解的“语言” • 机器语言的单词-指令,单词表-指令集 • 指令集:一个给定的体系结构所能理解的命令集合 • 所有的机器语言都非常类似 • 构成计算机的硬件技术基于相似的底层原理 • 一些基本操作是所有计算机都必须提供的 • 计算机设计者具有共同的目标: • 以最低的成本得到最好的性能 • 设计一种使硬件设计和编译器构造更简洁的语言
2.1 概述 • “设备简单性”是应当着重考虑的问题 • 本章将描述一个遵循该思路的指令集,并展示如何用硬件描述,以及其和高级语言的关系 • “存储程序”概念:指令和各种类型数据以数字形式存储在存储器中。 • 本书所描述的指令集是20世纪80年代以来设计的指令集MIPS • 在实验课中,我们将学习另外一种指令集IA-32,x86系列CPU使用的指令集
CPU Memory Devices Control Input Datapath Output Fetch Exec Decode 回顾:(von Neumann) Processor Organization
续: • Control needs to • input instructions from Memory • issue signals to control the information flow between the Datapath components and to control what operations they perform • control instruction sequencing • Datapath needs to have the • components – the functional units and storage (e.g., register file) needed to execute instructions • interconnects - components connected so that the instructions can be accomplished and so that data can be loaded from and stored to Memory
回顾:RISC - Reduced Instruction Set Computer Design goals: speed, cost (design, fabrication, test, packaging), size, power consumption, reliability, memory space (embedded systems) • RISC philosophy • fixed instruction lengths • load-store instruction sets • limited addressing modes • limited operations • MIPS, Sun SPARC, HP PA-RISC, IBM PowerPC, Intel (Compaq) Alpha, … • Instruction sets are measured by how well compilers use them as opposed to how well assembly language programmers use them
Registers R0 - R31 PC HI LO 3 Instruction Formats: all 32 bits wide R format OP rs rd sa funct rt I format OP rs rt immediate J format OP jump target 回顾:MIPS R3000 Instruction Set Architecture (ISA) • Instruction Categories • Computational • Load/Store • Jump and Branch • Floating Point • coprocessor • Memory Management • Special
回顾: Unsigned Binary Representation 231 230 229 . . . 23 22 21 20 bit weight 31 30 29 . . . 3 2 1 0 bit position 1 1 1 . . . 1 1 1 1 bit 1 0 0 0 . . . 0 0 0 0 - 1 232 - 1 232 - 4 232 - 3 232 - 2 232 - 1
回顾:American Std Code for Info Interchange (ASCII): 8-bit bytes representing characters
2.2 计算机硬件的操作 • 任何计算机都必须能完成算术运算指令 • 第一条MIPS汇编语言指令:加法运算指令 • 格式:add a, b, c • 每条MIPS运算指令仅仅执行一个操作,并只有3个操作数 • 下面指令序列完成了什么功能? • add a, b, c # The sum of b and c is placed in a. • add a, a, d • add a, a, e • #右边是注释,帮助理解程序
MIPS算术指令 • MIPS assembly language arithmetic statement add $t0, $s1, $s2 sub $t0, $s1, $s2 • Each arithmetic instruction performs only one operation • Each arithmetic instruction fits in 32 bits and specifies exactly three operands destination source1 op source2 • Operand order is fixed (destination first) • Those operands are all contained in the datapath’s register file($t0,$s1,$s2) – indicated by $
MIPS算术指令 • 上述要求符合硬件简单性的设计原则 • 操作数个数固定比不固定,所需硬件更简单 • 硬件设计四个基本原则之一: • 简单源自规整 • 两个例题: • 1、将a=b+c 和 d=a-e 编译为MIPS汇编指令 • 2、将 f = (g+h)-(i+j)编译为MIPS汇编语言指令
小结: • 到目前学到的MIPS汇编指令
2.3 计算机硬件的操作数 • MIPS的算术指令操作数必须直接取自寄存器 • 寄存器是计算机构成的基本元素 • 对程序员可见 • 和高级语言的变量相比,寄存器数量有限 • MIPS中有32个32位寄存器 • 个数有限,太多将延长时钟周期(电信号传输) • 硬件设计的第二个原则:越少越快 • 在计算机中经常涉及的一个概念:字 • 字所包含的二进制位数称为字长 • 不同计算机系统中字长可能不同 • MIPS中字为32位
使用寄存器编译C语句 • MIPS中使用0到31表示相应的寄存器,约定:用“$”符号后跟两个字符代表一个寄存器 • $s0, …$s7:寄存器; $t0,…, $t7:临时寄存器 • 翻译如下C语句: • f=(g+h)-(i+j),其中:f、g、h、i和j分别用$s0、 $s1、 $s2、 $s3和$s4代替 • 翻译后的代码: • Add $t0, $s1, $s2 • Add $t1, $s3, $s4 • Sub $s0, $t0, $t1
Register File 32 bits 5 5 5 32 32 32 src1 addr src1 data src2 addr 32 locations dst addr src2 data write data write control MIPS Register File • Holds thirty-two 32-bit registers • Two read ports and • One write port
MIPS Register File • Registers are • Faster than main memory • But register files with more locations are slower (e.g., a 64 word file could be as much as 50% slower than a 32 word file) • Read/write port 增加了冲突 • Easier for a compiler to use • e.g., (A*B) – (C*D) – (E*F) can do multiplies in any order vs. stack • Can hold variables so that • code density improves (since register are named with fewer bits than a memory location)
2.3.1 存储器操作 • 寄存器个数有限,只能保留少量数据 • 包含大量数据的数组、结构的数据结构,计算机将数据存放在内存中 • MIPS的算术运算只作用于寄存器,因此,必须有在存储器和寄存器之间传送数据的指令 • 这些指令称为“数据传送指令” • 为了访问某个字,必须给出其存储器“地址”,这时可以将存储器看做一个很大的一维数组
存字指令和取字指令 • 取指令:把数据从存储器复制到寄存器的数据传送指令 • 格式:lw $s1, 100($s2) # load word • 存指令:把数据从寄存器传送到存储器 • 格式:sw $s1, 100($s2) # store word • 数据传送指令中的常量叫“偏移量”offset • 存放基址的寄存器叫“基址寄存器” base register
例1:翻译如下C语句 • A是含100个字的数组,编译器将$s1、$s2分配给g、h,基址寄存器分配为$s3 • 翻译如下语句: • g = h +A [8] • MIPS指令 • lw $t0, 8($s3) • Add $s1, $s2, $t0
例2:翻译如下C语句 • 假设变量h放在$s2,数组A的基址放在$s3中,翻译如下MIPS汇编代码 • A[12]=h+A[8] • MIPS代码: • lw $t0, 32($s3) • Add $t0, $s2, $t0 • Sw $t0, 48($s3)
注意: • 编译器将:变量和寄存器对应起来;而将数组、结构这样的数据结构分配到存储器中相应位置,然后将其在M中的起始地址放入数据传送指令中 • 在程序中8位字节非常有用,很多系统按单个字节编址。在MIPS中,一个字包括4个字节,因此,连续字的地址相差4 • MIPS中字的起始地址必须是4的倍数,这称为“对齐限制” • 两种字节寻找方式:使用最左端(大端)字节的地址作为字地址,或者相反;MIPS采用前者
字节寻址的影响 • 字节寻址影响数组下标 • 在例1中,加到基址寄存器$s3的偏移量必须是4*8,否则将变为A[8/4]
2.3.2 常数或立即数操作数 • 程序中常常要使用常量 • 但目前的指令中,常数必须从R中取出,因此,在这之前必须将常数从M放到R中 • 为了避免这种方式,MIPS中提供了另外一种指令:立即数加 • Addi $s3, $s3, 4 • 立即数加说明了硬件设计的第三个原则:加速执行常用操作
注意: • 程序中变量个数远多于R个数,因此,编译器尽量将最常用的变量保存在R中,其他在M中 • 寄存器换出:将不常使用或稍后才使用的变量存放到存储器中的过程 • 硬件设计的原则:大小和速度快慢呈现反比关系(存储器层次结构)。 • 数据在R中将比在M中访问速度更快 • 数据在R中效率更高。 • 指令一次读2个R,并写入结果,传送指令每次只能读写一个数 • 因此,MIPS编译器必须有效地使用R
2.4 计算机中指令的表示 • 机器如何表示数? • 我们习惯采用十进制,计算机常用二进制 • 仅仅是数制不同而已,二、八、十、十六 • 实际中在计算机里以高低电平表示0或1 • 根据冯.诺依曼体系的特点,指令和数据一样存储在计算机中 • 指令也以一系列高低电平信号形式保存在计算机中,并以数字形式表示 • 每条指令的各个部分可以看做单个数字,将其拼在一起就形成了指令 • 所有的指令都使用到了R,必须规定R的名字如何对应R的序号
例题:将MIPS汇编指令翻译为机器指令 • 指令: add $t0, $s1, $s2 • 十进制表示: • 指令的每一段称为一个字段(field) • 第一个和最后一个字段组合说明该指令为加法 • 第二个字段表示第一个源操作数的R号(17=$s1) • 第三个字段表示第二个源操作数的R号(18=$s2) • 第四个字段表示存放目的操作数的R号(8=$t0) • 第五个字段没有用到 0 17 18 8 0 32
000000 10001 10010 01000 00000 100000 例题:将MIPS汇编指令翻译为机器指令 • 对应的二进制表示: • 上述形式称为机器语言:指令的数字形式;数字形式的指令序列称为机器代码 • 指令的这种设计称为指令格式 • 指令为32位,和字长一致,遵循“简单源自规整”的原则 • 但是直接二进制表示非常繁琐,出现了更简化一些的表示,十六进制 • 本书约定,在数的右下角标注“ten、hex、two”区别各种进制 • 在其他书中,有用 B、O、H分别表示二、十、十六 • 要熟悉进制转换,书中page 35的例题
op rs rt rd shamt funct MIPS字段 • 为了使讨论更简洁,重命名了MIPS各字段 • op 6-bits opcode that specifies the operation • rs 5-bits register file address of the first source operand • rt 5-bits register file address of the second source operand • rd 5-bits register file address of the result’s destination • shamt 5-bits shift amount (for shift instructions) • funct 6-bits function code augmenting the opcode
MIPS字段 • 问题:如果指令需要比上述字段长的字段时? • 取字指令包括2个R和一个常数 • 位移量限制了转移的范围 • 因此,在MIPS设计时,一方面要使所有指令长度相同,另一方面要让每条指令格式刚好合适 • 如何处理?遵循硬件设计的第四项原则: • 优秀的设计需要适当的折中 • 折中方案:所有指令长度相同,但不同的指令采用不同的指令格式。 • 存在不同的指令格式,如R型、I型、J型等
不同指令格式 • 下面的指令格式称为R型 • I型指令格式如下: • 16位的偏移可以使得取字指令得到相对基址偏移达到2^15范围的数据 • 注意,在这种指令格式下的MIPS汇编语言的字段含义有所不同 op rs rt rd shamt funct Op, 5b rs,5b rt,5b constant or address, 16bit
Memory . . . 0001 1000 + . . . 1001 0100 . . . 1010 1100 = 0x120040ac 2410 + $s2 = 0xf f f f f f f f 0x120040ac $t0 0x12004094 $s2 op rs rt 16 bit offset 0x0000000c 0x00000008 0x00000004 0x00000000 data word address (hex) I型取字指令 • Load/Store Instruction Format (I format) lw $t0, 24 ($s2)
不同指令格式的区分 • 多种指令格式使得硬件变得复杂 • 在MIPS中,机器根据第一个字段区分不同的指令格式 • R型、I型等,其第一个字段均为5位 • 每种格式的第一个字段op被分配一套不同的值,计算机可以据此确定指令后半部分是三字段还是一字段 • 参考37页表2-6
例子:翻译如下C语句为MIPS汇编指令 • A[300]=h+A[300] • 假定:数组A的基址在$t1, h-$s2 • 编译后的代码: • Lw $t0, 1200($t1) • Add $t0, $s2, $t0 • Sw $t0,1200($t1) • 参考37页中十进制表示的机器语言指令以及二进制的机器语言指令 • 参考38页,回顾已经学过的MIPS机器语言指令
重点: • 当前计算机构造基于2个关键性原则 • 1、指令以数据形式表示 • 2、和数据一样,程序存储在存储器中,并可读写 • 这两个原则导致了“存储程序”的概念 • 将指令当作数字使得程序被当作二进制数字文件发行;在商业上,计算机可以继承已有的与该指令集兼容的软件,这使得工业界目前围绕几个有限的指令体系构成不同的联盟
2.5 逻辑运算指令 • 对字里的特定几位进行操作也非常有用 • MIPS中加入了一些对某些位操作的指令,称为逻辑操作 • 图2-9中(p40)给出了对应的操作符以及对应于MIPS的指令 • 第一类:移位指令 sll和srl • Sll $t2, $s0, 4 • Op rs rt rd shamt func • 0 0 16 10 4 0 • 逻辑左移和右移相当于乘或者除操作
2.5 逻辑运算指令 • 第二类指令:逻辑操作 and(andi)、or(ori)、nor • And $t0, $t1, $t2 • And运算可以用0来屏蔽某些位(0与任何都为0) • Andi是和常数相与 • Or $t0, $t1, $t2 • Nor $t0, $t1, $t3 # ~( $t1| $t3) • NOT是取反操作,但是只需要一个操作数,为了保持双操作数的指令格式不变,引入或非NOR替代之,如果t3为0,则可以得到对t1取反的结果 • 参考p41页中图2-10的归纳
2.6 分支指令 • 计算机的智能在于其可以根据不同情况选择合适的指令执行 • 在程序中实现使用的是分支语句,如:if、go to、label等 • MIPS汇编语言中包括2条语句: • Beq register1, register2, L1 #相等时转 • Bne register1, register2, L1 #不相等时转 • 称为条件分支指令
例子:将if-then-else编译为条件分支指令 • If (i= =j) f=g+h; else f=g-h; • 设:f, …,j 分配到 $s0,…$s4 • MIPS指令序列: • Bne $s3, $s4, Else • Add $s0, $s1, $s2 • J Exit • Else: sub $s0, $s1, $s2 • Exit: • 注意:编译器经常产生分支指令和标号,但高级语言中并不出现。避免使用显式标号和分支,可以使得高级语言的编码效率提高
例子:循环语句的编译 • While (save[i]= = k) i + =1; • 假设:i和k对应$s3和$s5, save基址存于$s6 • Loop: sll $t1, $s3, 2 • Add $t1, $t1, $s6 • Lw $t0, 0($t1) • Bne $t0, $s5, Exit • Addi $s3, $s3, 1 • J Loop • Exit: • 以分支指令结束的指令序列对编译技术而言非常基础(称为基本块)。而编译的最初阶段就是将程序分为基本块。 • 基本块:除了可能在序列结尾处,序列中没有分支指令;除可能在序列开始处,序列中没有分支目标和分支标号
变量大小判断的实现 • 比较除了等于和不等于之外,也包括大小比较 • MIPS汇编指令: • slt $t0, $t3, $s4 #t3中的值小于t4中的将t0置1 • Slti $t0, $s2, 10 #立即数比较版本 • 为什么没有给出“小于时分支”指令? • 遵循“设备简单性”的原则,这类指令过于复杂 • MIPS编译器使用slt、slti、beq、bnq等指令和$zero中的定值0产生所有的比较条件:相等、不等、小于、小于等于、大于、大于等于
分支语句:case/switch语句 • Case/switch功能:根据变量的不同取值,选择不同的程序分支 • 实现switch的一种方法:利用条件判断序列,将switch语句转化为一些了if-then-else语句 • 另一种方法:通过编码形成一个分支指令序列地址表(转移地址表)。 • 程序查表获取目标地址,并跳转到相应的分支指令序列 • 转移地址表是一个字数组,数组中各元素对应代码中各个标号的地址 • MIPS中设计了一条无条件跳转指令jr支持上述实现 • 在高级语言中,虽然有各种不同的分支判断和循环语句,但实现他们的底层基础语句是条件分支 • 回顾:p45中图2-12,已经学习过的MIPS指令
2.7 计算机硬件的过程支持 • 过程或函数是结构化编程的有效工具 • 过程:使用参数将过程与其他程序和数据分开,只允许传值和返回结果 • 降低问题复杂度、提高程序的可读性、可重用性 • 在过程运行时,程序遵循如下六个步骤: • 将参数放在过程可以取到的位置 • 向过程传递控制 • 获得过程所需的存储资源 • 执行需要的任务 • 将结果的值放在调用程序可以获取到的地方 • 将控制返回到初始点
2.7 计算机硬件的过程支持 • R的速度最快,因此,在编译时需要尽可能多使用R,MIPS在对过程进行编译时使用R遵循如下规定: • $a0-$a3:传参数; $v0-$v1:返回值; $ra:返回起始点 • 另外,MIPS汇编语言有一条专门的过程指令:跳转到某个地址的同时将下一条指令的地址保存在寄存器$ra中 • 跳转-链接指令 jal procedureAddress • 链接指明调用位置的地址,存于$ra中 • 保存当前运行指令的地址寄存器:程序计数器PC • Jal指令将PC+4保存在$ra中 • 相应的,为了在过程调用结束时返回,MIPS设计了一返回指令:jr $ra
2.7.1 使用更多R • 程序中经常需要将R的内容换出到M • 如果要使用多于4个参数R或2个返回值R时 • 调用结束后恢复原数据 • 理想的数据结构是栈stack • 需要栈指针:指向最新分配的地址 • 两个操作:入栈push和出栈pop • MIPS中为栈分配了一个R:$sp • 惯例:栈增长实际中是存储器地址由高到低
例子:编译一个不调用其他过程的C过程 • 如p48中例题 • 假设:参变量g,h,I,j对应$a0,-$a3, f对应$s0 • MIPS编译后的指令序列: • Leaf_example: #过程从标号开始 • Addi $sp, $sp, -12 # 保存3个R • Sw $t1, 8($sp) • Sw $t0, 4($sp) • Sw $s0, 0($sp) • Add $t0, $a0, $a1 #对应过程实体 • Add $t1, $a2, $a3 • sub $s0, $t0, $t1 • Add $v0, $s0, $zero # 放入返回值 • Lw $s0, 0($sp) #恢复3个旧值 • Lw $t0, 4($sp) • Lw $t1, 8($sp) • Addi $sp, $sp, 12 • Jr $ra # 返回 • $t0-$t9,10个R为临时R, • 不需保存;$s0-$s7:8个 • 保留R,需要保存。这 • 个规定减少了R换出
2.7.2 嵌套过程 • 没有调用其他过程的过程称为叶过程 • 叶过程很简单,但是程序中存在嵌套的情况,甚至是自身递归,如:汉诺塔、计算n!等 • R有限导致可能存在R争用问题 • 解决:将所有需要保存的R压栈。 • 调用者将所有调用后仍需要的参数R($ax)或临时R($tx)压栈; • 调用者将返回地址R $ra和被调用者使用的被保存R($sx)压栈 • 栈指针sp随时调整计算栈中R的个数 • 返回时,R从M中恢复,栈指针重新调整
P50的例子 翻译如下: Fact: Addi $sp, $sp, -8 Sw $ra, 4($sp) Sw $a0, 0($sp) Slti $t0, $a0,1 Beq $t0, $zero, L1 Addi $v0, $zero, 1 Addi $sp, $sp, 8 Jr $ra L1: addi $a0, $a0,-1 Jal fact Lw $a0, 0($sp) Lw $ra, 4($sp) addi $sp, $sp, 8 Mul $v0, $a0, $v0 Jr $ra 例子:计算阶乘
对上述指令列的解释 • 一个C的变量就是一个存储位置,对其解释需要确定其类型和存储方式 • 两种存储方式:动态和静态。动态仅存在于过程中 • 静态变量则进入和退出过程时一直存在 • 在过程之外和用static声明的变量都是静态 • MIPS使用一个专门的R,全局指针$gp,用于简化静态数据的访问 • 参考p51中图2-15中过程保留的不保留的对象
2.7.3 在栈中为新数据分配空间 • 栈中保留数据的复杂性在于局部变量的存在 • 栈中保留R和局部变量的段称为过程帧 • 在MIPS软件中使用一个专门的R,帧指针$fp,指向过程帧的第一个字 • 帧指针提供了用于局部存储器引用的稳定基寄存器 • 避免在过程中修改$sp来保护$fp