原码, 反码, 补码
- 原码: 最高位表示符号位(无符号数不需要符号位)。剩下的位数,是这个数的绝对值的二进制
- 反码: 正数的反码和其原码是一样的. 负数的反码就是在其原码的基础上 符号位不变 其他位取反。
- 补码: 正数的补码就是其原码. 负数的补码就是在其反码的基础上+1
补码的加法
注: H
表示16进制数
正9, 负9 的补码表示及相加
// +09H
00001001 原码
// -9H
00001001 原码
11110110 反码
11110111 补码
// +09H + -09H
00001001 + 11110111 = 1,00000000
// 由于内存宽度的限制
1,00000000 = 00000000;
正128, 负128 的补码表示及相加
// +80H
// 10000000 原码
// -80H
10000000 原码
01111111 反码
10000000 补码
// +80H + -80H
10000000 + 10000000 = 1,00000000
// 由于内存宽度的限制
1,00000000 = 00000000;
综上, 进行加减法计算时不需要知道内存中保存的数据的正负
运算的时候不需要知道内存中保存的数据的正负, 但是读取的时候呢?
一字节内存有符号数取值范围
00000000-01111111 正数
10000000-11111111 负数
一字节内存无符号数取值范围
00000000-11111111 正数
如果能够知道一段内存中保存的是有符号还是无符号不就知道了其保存了么?
但是如何判断其保存的是有符号还是无符号?
其实, 打印作为一个高级语言才比较完善的功能, 是根据打印的需求确定是否为负数
而这个类型判断并不是来自对内存中数据的分析, 而是来自占位符.
比如C语言中的打印:
printf("%d",11);
上面的打印代码其实是告诉程序: 我要从'11'这个数字所在的内存中读取一个有符号数
当然汇编也可以打印, 但是并不能打印正负, 只能是根据程序猿需要自己添加正负号.