1,/;/ 深入理解计算机组成原理2
指令:
1.算数和逻辑指令:
2.加载有效地址:
指令为leaq 实际上是movq 指令的变形。他的指令形式是从内存读数据到寄存器,但他实际上不引用内存。他的第一个操作数看上去是一个内存引用,但是该指令并不是从特定位置读数,而是将有效地址写入到目的操作数
例子: 假设寄存器%rax的值为x,%rcx的值为y
一元操作, 操作数可以是一个寄存器,也可以是一个内存位置
二元操作数 第二个操作数,即使源,又是目的
移位操作: SAL 和SHL。只有右一操作才要求区分有符号和无符号
控制:
条件码 :
CF 进位标志,最近的操作是最高位产生了进位。可用来检查无符号操作的溢出
ZF;零标志。最近的操作得出的结果为0
SF:符号标志。最近的操作得到的结果为负数
OF: 溢出标志。最近的操作导致一个补码溢出
数据对齐:
现在的许多计算机系统对基本数据类型的合法地址做了一些限制,要求某种类型对象的地址必须是某个值K(通常是2,4,8)的背书。这种对齐限制简化了形成处理器和内存系统之间接口的硬件设计。
理解指针
指针是C语言的一个核心特色,他们以一种统一的方式,对不同的数据结构中的元素产生引用。
1.每个指针都对应一个类型。这个类型表明该指针指向的是哪一类对象
2.每个指针都有一个值。这个值是某个指定类型的对象的地址。特殊的NULL(0)值表示该指针没有指向任何地方
3.指针用&运算符创建 *运算符用来间接引用
4.数组和指针有着密切的关系。一个数组的名字可以像一个指针变量一样引用(但是不能修改)数组的引用和指针运算和间接引用(例如*(a+3))有一样的效果。数组的引用和指针的运算都需要用对象大小对偏移量进行伸缩。当我们写表达式p+i 这里的指针p的值为
p,得到的地址计算为p+L*i 这里L是与p相关联的数据类型的大小
5.可以将指针从一种类型映射强制转换为另一种类型
6.指针也可以指向函数。例如
定义一个函数指针 int (*fp)(int,int*)
一个函数为 int fun(int,int*p)
将指针指向函数fp=fun
就可以使用指针调用函数了
7.处理器处理阶段
1.取值:取址阶段从内存中读取指令字节,地址为程序计数器(PC)的值。从指令中抽取中抽取指令指示符字节的两个四位部分。称之为icode(指令代码)和ifun(指令功能)他可能取出一个四字节昌数字valc。他按照顺序方式计算当前指令的吓一跳指令地址valp。也就是说,valp等于pc的值加上已读取指令的长度。
2.译码:从寄存器翁建读取最多两个操作数,得到值valA和valB。通常,他读入指令rA和rB字段指明的寄存器,不过有些指令是读取寄存器%rsp
3.执行:在执行阶段,算数/逻辑单元(ALU)要执行指令的操作(根据ifun的值)计算内存设置条件码。对一条条件传送指0//
令来说,这个简短会检验条件码和传送条件(由ifun给出)。如果条件成立,则更新21Z
4.访存:访存阶段可以将数据写入内存,或者从内存中读取数据。读出的值为valM
5.写回:写回阶段最多可以写两个结果到寄存器文件中。
6.更新:将pc设置成下一个指令的地址。
流水线: 在流水线化系统中,待执行的任务被分为若干个独立的阶段。允许多个用户经过系统。流水线体感了系统的吞吐量,也就是单位时间内服务的用户数,不过它也会轻微的增加延迟,也就是服务一个用户所需要的时间。(产生的原因可能是插队)
计算流水线:有一些执行计算的逻辑以及一个保存计算结果的寄存器组成。时钟信号在特定时间加载寄存器。
在现代路基设计中,电路的延迟是以微微秒或者皮秒计算的。*也就是10的-12次方)
吞吐量=(1条指令)/(组合逻辑时间+加载寄存器时间)
我们以每秒千兆条指令(GIPS),也就是每秒十亿指令,为单位描述吞吐量,从头到尾执行一条指令所需要的时间叫做延迟。也就是吞吐量的倒数。