深入理解计算机系统 ¶
约 1012 个字 36 行代码 14 张图片 预计阅读时间 6 分钟 共被读过 99 次
1 计算机系统漫游 ¶
2 信息的表示和处理 ¶
- 把位组合再一起,再加上 interpretation
- 三种重要的数字表示
- unsigned
- two's-complement
- floating-point
- overflow
- 浮点数是近似的
2.1 信息存储 ¶
- 1 byte = 8 bits
- virtual memory
- address
- virtual address space
- 讲存储器空间划分为更可管理的单元,来存放不同的 program object
2.1.1 十六进制表示法 ¶
- 0x...
2.1.2 字数据大小 ¶
- word size
- nominal size
- 字长决定的最重要的系统参数就是虚拟地址空间的最大大小
- 为了避免大小和不同编译器设置带来的奇怪行为,我们有了 int 32_t 和 int 64_t
- C 语言对声明的关键词顺序不敏感
2.1.3 寻址和字节顺序 ¶
- [[ 计算机组成与设计硬件软件接口 #^da8be4| 小端编址 ]]
- 就是右边放小的,要从右往左读
- 字节顺序变得重要的三种情况
- 网络应用程序的代码编写必须遵守已建立的关于字节顺序的规则
- disassembler
- 编写规避正常的类型系统的程序
- cast or union in C
- 对应用编程不推荐,但是对系统级编程是必需的
C
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; i++)
printf(" %.2x", start[i]);
printf("\n");
}
void show_int(int x) { show_bytes((byte_pointer)&x, sizeof(int)); }
void show_float(float x) { show_bytes((byte_pointer)&x, sizeof(float)); }
void show_pointer(void *x) { show_bytes((byte_pointer)&x, sizeof(void *)); }
void test_show_bytes(int val) {
int ival = val;
float fval = (float)ival;
int *pval = &ival;
show_int(ival);
show_float(fval);
show_pointer(pval);
}
int main() {
int val = 12345;
test_show_bytes(val);
return 0;
}
2.1.4 表示字符串 ¶
2.1.5 表示代码 ¶
- 二进制代码很少能在不同机器和操作系统组合之间移植
2.1.6 布尔代数简介 ¶
- 可以扩展到位向量的运算
- 布尔代数
- Boolean ring
- additive inverse
- 和集合的对应
2.1.7 C 语言中的位级运算 ¶
- 掩码运算
2.1.8 C 语言中的逻辑运算 ¶
2.1.9 C 语言中的移位运算 ¶
- 逻辑右移
- 算数右移
- 实际上,几乎所有的编译器都对有符号数使用算术右移,而对于无符号数,右移必须是逻辑的(C 语言)
- 而对于 Java
x>>k
是算数右移,x>>>k
是逻辑右移 - 对于 C 语言,移动
- 加减的优先级比移位算法要搞
2.2 整数表示 ¶
2.2.1 整型数据类型 ¶
2.2.2 无符号数的编码 ¶
- 把向量写成二进制表示的数,就得到了无符号表示
- 无符号数编码的唯一性
2.2.3 补码编码 ¶
- two's-complement
- negative weight
- 原码
- 对于数字 0 有两种不同的编码方式
2.2.4 有符号数和无符号数之间的转换 ¶
- 保持位值不变,改变解释方式
- 补码转换为无符号数
- 无符号数转换为补码
2.2.5 C 语言中的有符号数与无符号数 ¶
2.2.6 扩展一个数字的位表示 ¶
- 无符号数的 zero extension
- 补码数的符号扩展
2.2.7 截断数字 ¶
2.2.8 关于有符号数与无符号数的建议 ¶
2.3 整数运算 ¶
2.3.1 无符号加法 ¶
- Lisp 支持无限精度的运算