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

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

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

在计算机底层的软件层面,我们通常采用二进制,八进制或十六进制来记录数字,其中最常用的是十六进制。所谓 n n n进制,就是从0开始数,逢 n n 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 n n位二进制数,只需要 ⌈ n 4 ⌉ \lceil\frac{n}{4}\rceil 4n位十六进制数即可。也就是说,我们要表示64位的地址,只需要16位十六进制数即可。

补码

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

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

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

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

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

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

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

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

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

逻辑运算

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

可以在哪看到这系列文章

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

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

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值