Skip to content

Latest commit

 

History

History
58 lines (34 loc) · 5.4 KB

macOS上的汇编入门(二)——数学基础.md

File metadata and controls

58 lines (34 loc) · 5.4 KB

在正式介绍汇编语言之前,我会先用几篇文章讲一些数学基础和硬件基础。如果读者已经具备了一定的知识基础,可以直接跳过这些文章去汇编语言部分。

二进制,八进制与十六进制

在计算机底层的软件层面,我们通常采用二进制,八进制或十六进制来记录数字,其中最常用的是十六进制。所谓$n$进制,就是从0开始数,逢$n$进1. 比如说二进制,就是从0开始数,到1,然后到2的时候进1变成10. 八进制也是类似,但是到了十六进制就犯了难,我们的数字只有0到9这十个,并不能表示出16个呀,于是,我们默认使用了a到f这六个字母来分别表示10到15这六个数。也就是说,十进制数10对应的十六进制数是a, 十进制数26对应的十六进制数是1a. 在计算机底层,通常用0x开头表示十六进制,用0开头表示八进制,而没有前缀来表示十进制。因此,比如说以下的汇编代码(并不需要理解实际含义)

movq $0x1a, %rax

movq $26, %rax

相同。

十进制数与十六进制数的转化可以在搜索引擎上找到,这里不再赘述。而八进制,十六进制数与二进制数的转换则十分简单。一个八进制数的一位代表一个二进制数的三位,比如说八进制数的一位5就代表二进制数的三位011; 同理,一个十六进制数的一位就代表二进制数的四位。因此,十六进制数0x2000001就代表二进制数0010000000000000000000000001.

我们知道,之所以使用二进制数,是因为计算机底层采用高电平/低电平这种方法来表示数。那么,我们为什么要使用八进制、十六进制呢?我们知道,如今的计算机大多采用64位系统,意思是说,任何一个地址都是一个64位二进制数。那么,如果我们只采用二进制来表示一个地址,那么得有64个0或者1, 这不仅让我们看花眼了,而且也极大的浪费了电脑的显示资源。而刚才讲到的十六进制数则帮我们解决了这个问题。我们知道,十六进制数的一位对应二进制数的4位。因此,一个$n$位二进制数,只需要$\lceil\frac{n}{4}\rceil$位十六进制数即可。也就是说,我们要表示64位的地址,只需要16位十六进制数即可。

补码

进制问题解决了在计算机底层软件中数的表示问题,接下来还需要解决的是记录问题,也就是说,如何把数实际存储在64位寄存器中。我们想要解决两个问题:

  • 如何记录负数
  • 可以使用加法器计算减法么

天才般的先行者,使用了补码来一举解决了这两个问题。

想要解决第二个问题,一个想法自然出现了,既然$a-b=a+(-b)$, 那可以在加法器中输入一个正数和一个负数来实现减法呀。

然而,我们知道,在计算机中,一个存储单位存储的数据大小是有上限的。比如说在64位CPU中,每个寄存器有64位,因此可以存储64位二进制数。因此,在CPU的加法器中,实际上使用了模$2^{64}$加法。也就是说,加法器做的,就是对于输入的两个64位二进制数$a$和$b$, 输出64位二进制数$(a+b)\bmod{2^{64}}$.

因此,我们只有找到合适的将负数记录成64位二进制数的方法,才能将加法器转化为减法器。

注意到 $$ a-b\equiv a+\left(2^{64}-b\right)\pmod{2^{64}} $$ 而由于$b$是64位二进制数,因此,$2^{64}-b$必然是一个正数,而正数的记录方法我们是知道的。因此,我们可以使用$2^{64}-b$来记录$-b$, 其参与的减法就可以变成相应的加法。

但是,还有一个细节需要注意。比如说,我们想要记录的二进制数是0xfffffffffffffffe, 那么根据刚刚讨论的,我们可以将其记录为0x1. 这就出现了问题,如何区分0x10xfffffffffffffffe呢?我们采用这种方法只是为了方便减法,并不打算将正数和负数混同啊。

因此,在实际操作中,当出现负数时,能够允许的负数的绝对值最大值是$2^{63}$. 换句话说,其记录值最高位0表示正数,1表示负数。这种记录方法叫做__补码__。也就是说,对于小于$2^{63}$的正数,采用其二进制表示为其实际记录;对于不低于$-2^{63}$的负数,将其加上$2^{64}$后的正数的二进制表示为其实际记录。如果采用补码,那么可以表示$-2^{63}\sim2^{63}-1$的整数。因此,采用补码记录的数称为__有符号整数__。反之,如果直接使用其二进制表示为其记录的话,那么只能表示$0\sim 2^{64}-1$的整数。因此,这种数的记录形式称为__无符号整数__。

逻辑运算

除了加减乘除以外,二进制数还有独特的运算——逻辑运算。分别是与(and), 或(or), 非(not)和异或(xor). 与或非大家都很熟悉了,异或就是当且仅当两个操作数不同时输出1, 相同时输出0.

可以在哪看到这系列文章

我在我的GitHub上,知乎专栏上和CSDN上同步更新。

上一篇文章:macOS上的汇编入门(一)——引言

下一篇文章:macOS上的汇编入门(三)——硬件基础