64位汇编语言的编程艺术
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.1 数制系统

大多数现代计算机系统都不使用十进制(以10为基数),而是通常采用二进制或者二进制补码(two's complement)的数制系统。

2.1.1 十进制数制系统的回顾

长期以来,人们一直使用十进制数制系统,因此可能会想当然地认为所有数字都是十进制数。现在,当看到像123这样的数字时,不要去考虑数值123,而是在大脑中考虑它总共代表多少项。实际上数字123在十进制数制系统中的表示如下:

(1×102)+(2×101)+(3×100

或者

100+20+3

在十进制的位置数制系统中,小数点左侧的每一位数字都代表一个数值,它们是0~9之间的数字乘以10的递增次方幂;小数点右侧的每一位数字也都代表一个数值,它们是0~9之间的数字乘以10的递增负次方幂。例如,123.456可以表示为:

(1×102)+(2×101)+(3×100)+(4×10-1)+(5×10-2)+(6×10-3

或者

100+20+3+0.4+0.05+0.006

2.1.2 二进制数制系统

在大多数现代的计算机系统中都采用二进制逻辑进行运算。计算机使用两个电平(通常是0V和+2.4~5V)表示数值,这两个电平正好可以表示两个不同的数值。这两个数值可以是任意两个不同的数值,但通常表示二进制数制系统中的两个数值0和1。

二进制数制系统与十进制数制系统的原理类似,不同之处在于二进制数制系统中仅存在0和1(而不是0~9),并且使用的是2的幂(而不是10的幂)。因此,将二进制数字转换为十进制数字非常容易。对于二进制字符串中的每个1,都要乘上2n,其中n是从0开始计数的1所在的位置。例如,二进制数110010102可以表示为:

(1×27)+(1×26)+(0×25)+(0×24)+(1×23)+(0×22)+(1×21)+(0×20

=12810+6410+810+210

=20210

总而言之,首先必须找到所有2的幂,然后将这些幂相加,结果就等于十进制数字。

将十进制数字转换为二进制数字要稍微复杂一些,一种简单方法是“偶/奇—除2”(even/odd—divide-by-two)算法。该算法使用以下的步骤。

(1)如果数字为偶数,则得到一个0。如果数字为奇数,则得到一个1。

(2)将数字除以2,并舍弃小数部分或余数。

(3)如果商为0,则算法完成。

(4)如果商不是0并且是奇数,则在当前二进制串前插入1;如果数字为偶数,则在当前二进制串前面加0。

(5)返回到步骤(2),并重复操作步骤。

虽然在高级计算机程序设计语言中,二进制数不太重要,但它们在汇编语言程序中随处可见。所以读者必须熟悉二进制数。

2.1.3 二进制约定

从最纯粹的意义上讲,每个二进制数都可以包含无限多位的数字,或者称为二进制位(bit,简称位,是binary digit的缩写)。例如,我们可以使用以下任意一种方式来表示数字5:

101 00000101 0000000000101 … 000000000000101

二进制数之前可以包含任意数量的前导0,而不改变其值的大小。由于x86-64通常使用8位的组,所以我们将使用前导0把所有二进制数扩展到4或者8的倍数位。按照这个约定,我们将5表示为01012或000001012。

对于较大的二进制数,为了增加其可读性,我们将每4位分为一组,组之间使用下划线分隔。例如,我们将1010111110110010写成1010_1111_1011_0010的形式。

注意:MASM不允许在二进制数的中间插入下划线。在较大数内部使用下划线分隔只是本书为便于阅读而采用的约定。

我们将按如下方式对每个二进制位进行编号。

(1)二进制数中最右边的位编号为第0位。

(2)从右向左的每一个二进制位连续编号。

一个8位的二进制数使用第0位~第7位的位置编号:

X7X6X5X4X3X2X1X0

一个16位的二进制数使用第0位~第15位的位置编号:

X15X14X13X12X11X10X9X8X7X6X5X4X3X2X1X0

一个32位的二进制数使用第0位~第31位的位置编号,依此类推。

第0位称为低阶(low-order,LO)位,有些人将其称为最低有效位(least signifcant bit)。最左边的位称为高阶(high-order,HO)位,或者称为最高有效位(most signifcant bit)。我们将通过中间位各自的位置编号来引用这些位。

在MASM中,可以将二进制数指定为以字符b结尾的0或1串。请记住,MASM不允许在二进制数中使用下划线。