鱼C论坛

 找回密码
 立即注册
查看: 2309|回复: 8

对于《编码奥秘》中的17章提到的“借位减”的原理百思不得其解,特此来求朋友们指点

[复制链接]
发表于 2012-3-18 13:49:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在看小甲鱼的汇编教程的时候,看了本小甲鱼推荐的《编码的奥秘》,感觉很不错,但是看到17章,我对于8位加法器进行16位减法的时候使用的借位减的机制很困惑,原文这样描述:

如果进行1 6位数减法运算,还需要一个新指令,称为“借位减”(Subtract with Borrow)。
通常,减法操作需要使减数取反且把加法器的进位输入置为1。因为进位通常不是1,所以往
往被忽略。在进行1 6位数减法运算时,进位输出应保存在进位锁存器中。高字节相减时,进
位锁存器的结果应作为加法器的进位输入。


但是我想了很久也理解不了这段话,不知道怎么去理解这个“借位减”的具体步骤是怎么样的,如果哪位朋友知道,希望能指点下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-3-18 15:06:55 | 显示全部楼层
本帖最后由 wAterLoo 于 2012-3-18 15:40 编辑

首先你要明白
减法操作其实就是 对获得减数的补码,然后再与被减数相加
那么什么是补码呢?
举个例子,求二进制数 00000001 的补码
首先要将00000001 取反, 取反也就得到 111111110
取反后得到的数 再加一 就是 这个数的补码了 也就是 11111111
我们来看看 二进制减法 的操作
00000010() - 00000001(减数) 也就是 2 -1 = 1 对吧
首先对减数取反,然后+1,得到 11111111
再与被减数相加
  00000010
+11111111
100000001 由于这是8进制的减法运算,所以发生了溢出,我们只取右边8位 也就是 00000001 作为结果
这就是一个减法的操作
我记得书中取反是用一个叫做反向器的装置,取反后只是得到反码,补码 = 反码 + 1
这也是要取反 + 1 了

至于借位减法, 比如说 11 - 9 ,由于个位数 1 - 9等于负数,所以要向10位借一
其实"借位减法"在CPU是不存在的,因为减法操作都被转成加法操作了
你也看到,书中的“借位减”是打上引号的
16进制的减法 先要对减数取补,也就是得到减数的补码
取补后再把减数的低8位 和 被减数的低8位相加 , 注意这里可能会产生进位
再把取补后的减数的高8位 + 被减数的高8位 + 进位(这里的进位是前面的低8位相加产生的,如果低8为没有进位,这时候就等于0,否则就等于1)




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-3-18 15:13:28 | 显示全部楼层
想学习 顶顶呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-3-18 18:15:52 | 显示全部楼层
本帖最后由 lionfun 于 2012-3-18 18:18 编辑

你的这句话
16进制的减法 先要对减数取补,也就是得到减数的补码

提醒了我,文章说在进行16加法的时候,首先要进行低8为相加,如果有进位输出,则在进行高8位相加的时候作为进位输入,这个没有问题;但是说到16位减法的时候,也说低8位相减,如果有进位输出,则作为高8为的进位输入。我之前老是错误的理解既然分别进行低和高8位的相减,那么都要先对减数取反加1,然后我就总是理解不了低8为相减的产生的这个这个借位用来做什么,原来是我一直理解错误了。

取补只是对低8位的减数取补,而高8位取补还是取反只是一个结果,要看进位输入(也是低8位的借位减)是1还是0,为什么这么说呢,我做了两个例子来理解。
例子1:
2356H - 2079H
先进行低8位相减:
56H的2进制码为:01010110,79H的二进制码为:01111001,先求-79H的补码(79H取反加1)为:10000111,将上面的式子转化为2进制相加
01010110
+10000111
---------------
11011101
结果直接当做原码即16进制的DD,可以看出没有进位,借位减为0,我们接着进行高8位相减:

23H的2进制码为:00100011,20H的反码(注意是反码,不是补码)为:11011111,由于低8位相减没有进位不用加1则:
00100011
+11011111
----------
100000010
结果有溢出,只取右边8位,即:00000010作为结果,转为16进制为2H
最终的结果就是:2DDH

例子2:
2356H - 2020H
为了方便,取的被减数和例子1的相同。先进行低8位相减:
56H的2进制码为:01010110,20H的2进制码为:00100000,同样先求-20H的补码(20H取反加1)为:11100000,转化为2机制相加
01010110
+11100000
-----------
100110110
结果溢出,只取右边8位,即:00110110,16进制为:36H,由于有溢出借位减为1,我们接着进行高8位相减:

23H的2进制码为:00100011,20H的反码(注意是反码,不是补码)为:11011111,由于低8位相减有进位(即借位减)20H的反码要加1即:11100000,则:
00100011
+11100000
----------
100000011
结果有溢出,只取右边8位,即00000011作为结果,转为16进制为3H
最终的结果就是:336H

这样就明白了,所谓的“借位减”,就是低8位每次相减都要从高位借一位,这个可以通过取反再加1实现,例如8位2进制x(针对负数)取反,其实就是( 11111111 - x + 1) = (100000000 - x),如果进行进行的是低8位相减这个100000000就是认为是从高8位借来的,借是要借的,用不用要看实际情况了,比如例子1就用了这个借位,所以借位减为0,意思是不用还这个100000000给高位了,因为56H比79H小;例子2呢,虽然他也借了100000000,但是他用不着,因为56H比20H大,所以借位减为1,意思是把这个借来的100000000还给高位,所以高位进行运算的时候有个进位1就是这么来的,原来这个“借位减”的意思是“借了要减掉”到底是减0还是减1,就看低8位相减要不要用了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-3-18 18:18:36 | 显示全部楼层
lionfun 发表于 2012-3-18 18:15
你的这句话提醒了我,文章说在进行16加法的时候,首先要进行低8为相加,如果有进位输出,则在进行高8位相 ...

:lol:lol:lol:lol:lol

我在学习的时候也在这里停顿过
总之懂了就好

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-3-18 18:20:49 | 显示全部楼层
wAterLoo 发表于 2012-3-18 18:18
我在学习的时候也在这里停顿过
总之懂了就好

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-3-18 18:26:12 | 显示全部楼层
本帖最后由 wAterLoo 于 2012-3-18 18:26 编辑
lionfun 发表于 2012-3-18 18:15
你的这句话
提醒了我,文章说在进行16加法的时候,首先要进行低8为相加,如果有进位输出,则在进行高8位 ...

你这样理解也是没错的,但是呢,计算不会这么做
因为还有更高效的放
其实减数不用分低8位还是高8是否取补
直接将16位减数取补就行了
然后将取的补数,用adc指令 和被减数 相加 就OK了


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2012-3-18 18:50:57 | 显示全部楼层
wAterLoo 发表于 2012-3-18 18:26
你这样理解也是没错的,但是呢,计算不会这么做
因为还有更高效的放
其实减数不用分低8位还是高8是否取 ...

总的来看,都是一样的,只是换了一个思维,本质还是你说的减数直接取补。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-7-25 22:12:45 | 显示全部楼层
还在么 编码的奥秘是他在哪一课介绍的 能告诉我么?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-17 05:40

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表