Number In Machine
数的编码表示
真值 是符合人类习惯的数值写法,例如 $+15$、$-8$。
机器数 是数值实际存入计算机时的 bit 模式。对于负数,符号也必须被编码成 bit。
| 真值 | 一种机器表示示意 |
|---|---|
| $+15$ | 0 1111 |
| $-8$ | 1 1000 |
1000 可以是无符号数 $8$,也可以在 4 位补码中表示 $-8$。bit 串本身不携带解释规则。
无符号数
n 位无符号整数全部 bit 都是数值位,表示范围为:
$$
0 \le x \le 2^n - 1
$$
例如 8 位无符号整数的范围是:
$$
0 \le x \le 255
$$
无符号数适合表示地址、长度、计数值等不需要负数的对象。
有符号定点数
有符号定点数需要用某种编码规则表示正负号。常见编码包括:
- 原码
- 补码
- 移码
若真值为 $x$,常写作:
- $[x]_{\text{原}}$
- $[x]_{\text{反}}$
- $[x]_{\text{补}}$
- $[x]_{\text{移}}$
原码
原码用最高位表示符号,数值位表示真值的绝对值。
| 符号位 | 含义 |
|---|---|
| 0 | 正数 |
| 1 | 负数 |
例如 8 位机器字长:
| 真值 | 原码 |
|---|---|
| $+19$ | 0,0010011 |
| $-19$ | 1,0010011 |
若机器字长为 $n+1$ 位,其中 $n$ 位为数值位,则原码整数范围为:
$$
-(2^n-1) \le x \le 2^n-1
$$
原码的真值 0 有两种表示:
0,000...01,000...0
补码
补码规则:
- 正数补码与原码相同。
- 负数补码等于其反码末位加 1。
实质是:n 位补码的最高位权重为负,其余位权重为正。
例如 4 位补码的位权是:
$$
-2^3,\ 2^2,\ 2^1,\ 2^0
$$
所以:
$$
5_{10} = 0 + 4 + 0 + 1 = 0101_2
$$
而
$$
-5_{10} = -8 + 0 + 2 + 1 = 1011_2 = 0101_{2}\text{按位取反再加}1
$$
按位取反再加1即为取相反数操作,所以负数补码转回正数补/码的方法相同
补码整数范围为:
$$
-2^n \le x \le 2^n-1
$$
补码的真值 0 只有一种表示,因此比原码和反码多表示一个最小负数 $-2^n$即$\displaystyle 1\quad\underbrace{0…0}_{n\text{个}0}$
补码让减法可以转化为加法,这是整数运算电路统一化的基础。
移码
移码是补码加上一个固定的数,字长$n+1$位通常取$2^{n}$
| 真值 | 补码 | 移码 |
|---|---|---|
| $+19$ | 0,0010011 |
1,0010011 |
| $-19$ | 1,1101101 |
0,1101101 |
移码只能用于表示整数。若机器字长为 $n+1$ 位,则移码整数范围与补码相同:
$$
-2^n \le x \le 2^n-1
$$
移码的一个重要特点是:编码值越大,真值越大,因此很适合比较大小。IEEE 754 浮点数的阶码采用偏置编码,思想上与移码相近。
定点整数与定点小数
定点数的小数点位置固定。
定点整数
定点整数的小数点默认在最低位之后。
例如:
1 | 0,0010011 |
可以解释为一个带符号定点整数编码。
定点小数
定点小数的小数点默认在符号位之后、数值位之前。
例如:
1 | 0.1100000 |
可以解释为 $+0.75$ 的一种定点小数表示。
表示范围
若机器字长为 $n+1$ 位,则常见范围如下:
| 编码 | 定点整数范围 | 定点小数范围 |
|---|---|---|
| 原码 | $-(2^n-1) \le x \le 2^n-1$ | $-(1-2^{-n}) \le x \le 1-2^{-n}$ |
| 反码 | $-(2^n-1) \le x \le 2^n-1$ | $-(1-2^{-n}) \le x \le 1-2^{-n}$ |
| 补码 | $-2^n \le x \le 2^n-1$ | $-1 \le x \le 1-2^{-n}$ |
| 移码 | $-2^n \le x \le 2^n-1$ | 不用于定点小数 |
数据的存储和排列
一个多字节数据在内存中一定占用连续的若干字节。因此需要讨论字节的顺序以及数据的第一个字节的地址。
大小端模式
大小端源自《格列佛游记》,指“打破鸡蛋从大端/小端开始”。
在CS中描述的是多字节数据在内存中的字节排列顺序。
以 4 字节整数 0x01234567 为例,它由 4 个字节组成:
1 | 01 23 45 67 |
其中:
01是最高有效字节,MSB。67是最低有效字节,LSB。
若地址从低到高递增:
| 模式 | 低地址 -> 高地址 | 解释 |
|---|---|---|
| 大端模式 | 01 23 45 67 |
低地址放最高有效字节(大端) |
| 小端模式 | 67 45 23 01 |
低地址放最低有效字节(小端) |
0x01234567 的数值没有变。大小端只影响它拆成字节后在内存中的摆放顺序。
边界对齐
- 对于普通数据成员,起始位置落在该数据大小的整数倍地址上。第一个数据成员放在
offset=0的地方。 - 对于结构体成员,起始位置落在内部最大元素大小的整数倍地址上。
- 结构体大小应是内部成员中最大对齐参数(对齐参数一般等于元素大小)的整数倍。
对齐访问时,一个字可能一次访存就能读出。未对齐访问时,数据可能跨过存储字边界,需要两次访存,再由硬件拼接。
边界对齐主要是为了提高访存效率,也能简化硬件处理。
有些体系允许未对齐访问但速度较慢,有些体系可能直接禁止某些未对齐访问。