计算机组成原理学习基础(一)

性能指标
  1. 响应时间快
  2. 吞吐率大
  3. CPU 时钟周期数=指令数*每条指令的平均时钟周期数(CPI)
  4. 时钟周期时间(Clock Cycle) 我们程序可以识别出来的最小时间单位 比如电脑的主频是2.8GHz 可以粗浅的认为CPU在1秒内可以执行2.8GHz条简单的指令,由晶体振荡器来完成每一次时间的滴答,主频越高就意味着CPU跑的越快 但是跑的越快耗电量就越高 达到物理极限会崩溃 所以也是有上限的
  5. 程序CPU执行时间=指令数 * CPI * 时钟周期时间
指令

一、指令集

  1. 指令集 例如 手机端开发的程序没办法在电脑上运行 因为他们的CPU所支持的指令集不同,一套指令集就相当于是套CPU可以识别的语言。
  2. 对于存储程序型计算机 指令通常存储在存储器中

二、从代码到汇编到指令

  1. 添加代码
int main(){
	int a = 1;
	int b = 2;
	a = a + b;
}
  1. 编译- 从代码到汇编-机器码
gcc -g -c test.c  // 生成汇编代码
objdump -d -M intel -S test.o // 查看机器码

如下是源代码 汇编代码和机器码的一一对应关系

test.o:     文件格式 mach-o-x86-64


Disassembly of section .text:

0000000000000000 <_main>:
int main(){
   0:	55                   	push   rbp
   1:	48 89 e5             	mov    rbp,rsp
   4:	31 c0                	xor    eax,eax
	int a = 1;
   6:	c7 45 fc 01 00 00 00 	mov    DWORD PTR [rbp-0x4],0x1
	int b = 2;
   d:	c7 45 f8 02 00 00 00 	mov    DWORD PTR [rbp-0x8],0x2
	a = a + b;
  14:	8b 4d fc             	mov    ecx,DWORD PTR [rbp-0x4]
  17:	03 4d f8             	add    ecx,DWORD PTR [rbp-0x8]
  1a:	89 4d fc             	mov    DWORD PTR [rbp-0x4],ecx
}
  1d:	5d                   	pop    rbp
  1e:	c3                   	ret

三、指令分类

  1. 算数类指令,例如加减乘除
  2. 数据传输类指令,例如给变量赋值
  3. 逻辑类指令,例如与或非
  4. 条件分支类指令,if/else
  5. 无条件跳转指令,例如函数调用

按照R I J 分类
R 算数类和逻辑操作
I 数据传输 条件分支
J 跳转指令

寄存器

一、解释
CPU内部是由多个寄存器组成 寄存器是由一个或者多个触发器或者锁存器组成,例如一个触发器就可以组成一个一位的寄存器,寄存器是由门电路组成的,N位寄存器就可以保存N位的数据 例如64为计算机 就可以有64位寄存器

二、3中主要类型的寄存器

  1. PC寄存器也叫做指令地址寄存器 保存的是下一条计算机要执行的计算机指令地址
  2. 指令寄存器 保存当前正在执行的寄存器
  3. 条件码寄存器 用一个一个标记位 存放计算的结果

三、if/else 看程序的执行

  1. 添加如下代码
#include <time.h>
#include <stdlib.h>
int main(){
	srand(time(NULL));
	int r = rand()%2;
	int a = 10;
	if (r == 0){
		a = 1;
	}
	else {
		a = 2;
	}
}
  1. 看汇编和机器码
test.o:     文件格式 mach-o-x86-64


Disassembly of section .text:

0000000000000000 <_main>:
#include <time.h>
#include <stdlib.h>
int main(){
   0:	55                   	push   rbp
   1:	48 89 e5             	mov    rbp,rsp
   4:	48 83 ec 10          	sub    rsp,0x10
   8:	31 c0                	xor    eax,eax
   a:	89 c7                	mov    edi,eax
   c:	c7 45 fc 00 00 00 00 	mov    DWORD PTR [rbp-0x4],0x0
	srand(time(NULL));
  13:	e8 00 00 00 00       	call   18 <_main+0x18>
  18:	89 c7                	mov    edi,eax
  1a:	e8 00 00 00 00       	call   1f <_main+0x1f>
	int r = rand()%2;
  1f:	e8 00 00 00 00       	call   24 <_main+0x24>
  24:	99                   	cdq
  25:	b9 02 00 00 00       	mov    ecx,0x2
  2a:	f7 f9                	idiv   ecx
  2c:	89 55 f8             	mov    DWORD PTR [rbp-0x8],edx
	int a = 10;
  2f:	c7 45 f4 0a 00 00 00 	mov    DWORD PTR [rbp-0xc],0xa
	if (r == 0){
  36:	83 7d f8 00          	cmp    DWORD PTR [rbp-0x8],0x0
  3a:	0f 85 0c 00 00 00    	jne    4c <_main+0x4c>
		a = 1;
  40:	c7 45 f4 01 00 00 00 	mov    DWORD PTR [rbp-0xc],0x1
	}
  47:	e9 07 00 00 00       	jmp    53 <_main+0x53>
	else {
		a = 2;
  4c:	c7 45 f4 02 00 00 00 	mov    DWORD PTR [rbp-0xc],0x2
	}
}
  53:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
  56:	48 83 c4 10          	add    rsp,0x10
  5a:	5d                   	pop    rbp
  5b:	c3

上边汇编代码 cmp是一个比较指令 jne是jump if not equal 如果不相等就执行jmp指令跳转到4c的位置 把a赋值成2

这里 jump jle jne 都是跳转到指定地址的跳转指令

四、看循环如何执行

  1. 增加如下代码
int main(){
	int a = 0;
	for (int i = 0; i < 3; i ++){
		a += 1;
	}
}
  1. 看汇编和机器码
test_for.o:     文件格式 mach-o-x86-64


Disassembly of section .text:

0000000000000000 <_main>:
int main(){
   0:	55                   	push   rbp
   1:	48 89 e5             	mov    rbp,rsp
   4:	c7 45 fc 00 00 00 00 	mov    DWORD PTR [rbp-0x4],0x0
	int a = 0;
   b:	c7 45 f8 00 00 00 00 	mov    DWORD PTR [rbp-0x8],0x0
	for (int i = 0; i < 3; i ++){
  12:	c7 45 f4 00 00 00 00 	mov    DWORD PTR [rbp-0xc],0x0
  19:	83 7d f4 03          	cmp    DWORD PTR [rbp-0xc],0x3
  1d:	0f 8d 17 00 00 00    	jge    3a <_main+0x3a>
		a += 1;
  23:	8b 45 f8             	mov    eax,DWORD PTR [rbp-0x8]
  26:	83 c0 01             	add    eax,0x1
  29:	89 45 f8             	mov    DWORD PTR [rbp-0x8],eax
	for (int i = 0; i < 3; i ++){
  2c:	8b 45 f4             	mov    eax,DWORD PTR [rbp-0xc]
  2f:	83 c0 01             	add    eax,0x1
  32:	89 45 f4             	mov    DWORD PTR [rbp-0xc],eax
  35:	e9 df ff ff ff       	jmp    19 <_main+0x19>
	}
}
  3a:	8b 45 fc             	mov    eax,DWORD PTR [rbp-0x4]
  3d:	5d                   	pop    rbp
  3e:	c3                   	ret

解释上述代码

  1. mov DWORD PTR [rbp-0x8],0x0 把0给了a 也就是赋值到了0x8 地址
  2. mov DWORD PTR [rbp-0xc],0x0 循环第一次把 0 给到0xc
  3. cmp DWORD PTR [rbp-0xc],0x3 循环比较 0xc 是否和3相等 如果相等就到3a地址结束
  4. 如果不相等就 jmp 19 <_main+0x19> 继续执行
总结

我们平时写的代码都是高级语言 为什么说的是高级语言 因为我们不用接触汇编 更不用接触机器指令,所有的操作都让编译器帮我们做了 Xcode Studio等都可以帮助我们编译 然后生成汇编 最后生成可执行文件 到我们的磁盘中 程序执行的时候再把指令一条条的读到PC寄存器中 然后由CPU计算

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值