一、计算机组成
1. cpu
1.1. 指令周期、cpu周期、时钟周期
- 一个指令周期包含取指令和执行指令,包含多个cpu周期
- 一个cpu周期包含多个时钟周期
二、机器码
1. 补码
1.1. 为什么要有补码
做一个假设,要计算 $-1 + 1 = 0$ ,如果没有补码,计算转二进制(按照8bit算)是
$$
00000001 + 10000001
$$
需要判断首位,来处理是加还是减,增加了加法器的复杂度。
使用补码将是
$$
000000001 + 11111111 = 100000000
$$
第九位舍弃,使用加法器可以直接实现。所以补码是为了将符号位一起参与运算,减少硬件复杂度而出现的设计。
1.2. 补码转化
- 正数补码是本身
- 负数补码是对应的正数取反加一
$$
-1 = \neg 1 + 1 = 11111110 + 00000001 = 11111111
$$
三、数据和地址
1. 地址对齐
- 32位和64位机器的区别在于地址的表示是用32位还是64位表示
- 由此可以得出计算机对于内存的操作是按照整32位和整64位操作的,这样效率最高
- 所以对于c语言中结构体的定义,一般是默认4字节对齐或者8字节对齐
- 内存中的结构体的储存是在以4字节或8字节为单位的内存块中
- 那么可以说明结构体的首地址一定是4的倍数或8的倍数
举例,按照32位举例,64位类似
1 | struct rb_node { |
- 上面的结构体是4字节对齐,说明
rb_node
结构体在内存中的存储一定是4的倍数 - 因为地址中每个地址代表一个8位的内存块,对于cpu来说,一次读取一个内存块是4个字节的
- 如果要处理结构体,从效率来说,将结构体存到4的倍数是可以直接读取到首地址,不然还要偏移
- 所以上面的结构体,地址一定是4的倍数,也就是
0x00
、0x04
、0x08
这样的,后两位一定是0