这篇博客借鉴于深入理解计算机系统的第二章,也算是我看完书后的总结。
我们一般研究三种重要的数字表示,第一种是无符号编码,它是基于传统的二进制表示法,一般表示的是大于或等于的零的数字。第二种是补码编码,它是有符号整数最为常见的表达方式,有符号整数是可以为正或可以为负的整数,第三种是浮点数的编码,是以2位基数的实数的科学计数法的表示。
目的
为什么要研究数字表示?是为了我们能够了解表示的值的范围和不同算术运算的属性。
我们了解值的范围和不同算术运算的属性又是为了什么呢?第一是为了程序员所使用的所有数据都可以在数值范围内正常的工作。而且具有可以跨越不同机器、操作系统和编译器组合的可移植性。第二是为了能够理解编译器产生的机器代码。
先讲第一节 信息存储
目录
- 十六进制表示法
- 字数据大小
- 寻址和字节顺序
- 表示字符串
- 表示代码
- 布尔代数简介
- C语言中的位级运算
- C语言中的逻辑运算
- C语言中的移位运算
一般机器级程序将内存视为一个很大的字节数组,成为虚拟地址。内存中的每个字节都有一个唯一的数字来标识,称为地址,我们把所有地址的集合称为虚拟地址空间。
十六进制表示法
一个字节由8位组成。在二进制表示法中,字节的值域一般为0000 0000~1111 1111 转换成十进制也就是0-255,但是二进制和十进制表示法对于描述位模式都不是十分的方便。二进制表示法过于冗长,十进制表示法和位模式的互相转换,又十分的困难。因此,我们提出十六机制。用数字‘0’-‘9’,‘A’-‘F’来表示16个可能的值。在十六进制表示法中,字节的值域表示为00~FF。在C语言中,我们一般以开头0x或0X开头的数字常量被认为是十六进制的值。字符‘A’-‘F’可以大写,也可以小写,甚至可以混合写。
编写机器级程序的一个常见任务就是在位模式下将二进制、十进制、十六进制表示互相转换。
二进制转换成十进制,十六进制转换成十进制,比如将1111 1111转换成十进制,1*2^0+1*2^1+1*2^2+1*2^3+1*2^4+1*2^5+1*2^6+1*2^7=255
将FF转换成十进制F*16^0+F*16^1=255
十进制转换成二、十六进制 用除法除以基数2或16,得到的商倒排就能得到相应的进制。
不管是几进制和十进制的相互转换,一般都符合上面的转换规则。
而二进制和十六进制的比较有技巧。我们来举个例子。 十六进制0X173A4C转换成二进制。
1 7 3 A 4 C
0001 0111 0011 1010 0100 1100
一位十六机制等于4位的二进制,因此,我们将十六进制对应的数字转换成二进制数字即可。
二进制转换成十六进制也是如此,如果二进制的位数刚好是4的倍数,那就将按4位将二进制划分好,在转换成相应的十六进制。如果不是4的倍数,那就在二进制左侧补0,将位数添成4的倍数,再按上述的算法计算。
字数据大小
每台计算机都有一个字长,指明指针数据的标称大小,因为虚拟地址是以这样的一个字来编码的,所以字长决定最重要的系统参数就是虚拟地址空间的最大大小。对于一个字长为w位的机器而言,虚拟地址的范围为0~(2^w)-1,程序最多访问(2^w)个字节。
因此,32位机器的虚拟地址空间为4GB,64位机器的虚拟地址空间为16EB。
计算机和编译器支持多种不同方式编码的数据格式,这里给出各种数据格式在32位机器和64位机器,不同的典型值。