现代计算机组成与体系结构
上QQ阅读APP看书,第一时间看更新

1.3.1 二进制数和十六进制数

无论如何,处理器中的电路都不能直接处理数字。处理器电路元件遵循电学和电子学定律,并只对提供给它们的输入做出响应。驱动这些响应的输入来自程序员开发的代码和作为输入提供给程序的数据。例如,将程序的输出解释为电子表格中的数字或字处理程序中的字符,是对处理器内电信号交互的结果赋予意义的纯人工解释。决定将0分配给低电压、将1分配给高电压是解释过程中的第一步。

数字计算机中的最小信息单位称为位(bit),表示离散值0或1。将多个位组合在一起可以表示更大范围的值。一个字节(byte)由8个位组成。字节是大多数现代处理器可以从内存读取或写入内存的最小信息单位。

一个位可以取2个值:0和1。两个位组合在一起可以取4个值:00、01、10和11。三个位组合在一起可以取8个值:000、001、010、011、100、101、110和111。事实上,任何n位数都可以取2n个值,其中2n表示将n个2相乘。因此,一个字节可以表示28(256)个不同的值。

当执行计算任务时,二进制数格式并不是大多数人的首选,使用11101010等数字可能会令人困惑且容易出错,尤其是在处理32位和64位值时。为了更容易地使用这些数字,通常采用十六进制数,术语十六进制(hexadecimal)通常缩写为hex。在十六进制数字系统中,二进制数被分成4位一组。由于每组中有4个位,因此可能的数值个数是24(16)。这16个数字中的前10个数字为0~9,最后6个为字母A~F。表1.1显示了从0开始的前16个二进制值,以及相应的十六进制数字和十进制数字。

表1.1 二进制数、十六进制数和十进制数

二进制数11101010可以通过先将其分成两个4位组(1110和1010),然后写成十六进制数字EA来更紧凑地表示。因为二进制数只能取两个值,所以二进制数是以2为基数的数制。每位十六进制数字可以取16个值,因此十六进制以16为基数。每位十进制数字可以有10种值,因此十进制数以10为基数。

当使用这些不同的数制时,情况可能会变得复杂。形式为100的数字是二进制数、十六进制数还是十进制数?如果没有额外的信息,你就无法进行判断。各种编程语言和教材都采取了不同的方法来消除这种歧义。在大多数情况下,十进制数字是默认的,因此数字100通常是十进制数。在编程语言(如C和C++)中,十六进制数使用前缀0x,因此数字0x100是十六进制数。在汇编语言中,可以使用前缀字符$或后缀字符h来表示十六进制数。编程中使用二进制值的情况较少,主要是因为十六进制的紧凑性更好。某些编译器支持将0b用作二进制数的前缀。

十六进制数表示法

本书使用前缀$或后缀h来表示十六进制数,具体取决于上下文。后缀b表示二进制数,没有前缀或后缀的数字表示十进制数。

位在二进制数内单独编号,位0是最右边的最低有效位。位的编号从右向左递增。例如,在表1.1中,二进制值0001b(十进制数1)的位0被置位(set),其余三位被清除(clear)。在0010b(十进制数2)中,位1被置位,其余位被清除。在0100b(十进制数4)中,位2被置位,其余位被清除。

置位与清除

置位(set)的位其值为1,清除(clear)的位其值为0。

一个8位字节可能是$00~$FF的值,相当于十进制范围0~255。当执行字节加法时,结果可能超过8位。例如,将$01与$FF相加得到$100。使用8位寄存器时,该表示产生了进位,必须进行适当的处理。

在无符号运算中,从$00减去$01得到$FF,这构成了回绕。根据正在执行的计算,得到的可能是期望的结果,也可能不是期望的结果。

如果需要,负值可以用二进制数表示。现代处理器中最常见的有符号数据格式是二进制补码。在二进制补码中,8位有符号数字的范围为-128~127。二进制补码数的最高有效位是符号位:0表示正值,1表示负值。通过对所有位取反加1并忽略任何向最高位的进位,可以求得任意数字的二进制补码(参见表1.2)。对位取反意味着将0变为1,将1变为0。

表1.2 取反运算示例

需要注意的是,与数学中的定义一致,负零也是零。

二进制补码运算

二进制补码的位运算与无符号的位运算相同,无论输入值是有符号的还是无符号的,加法和减法所涉及的操作都是相同的。将结果解释为有符号或无符号完全取决于用户的意图,参见表1.3。

表1.3 有符号和无符号的8位数字

二进制数的有符号和无符号表示形式可以扩展到更大的整数数据类型。16位值可以表示0~65535的无符号整数和-32768~32767的有符号整数。在现代编程语言中通常使用32位、64位甚至更大的整数数据类型。