请大家帮忙解惑,关于溢出的困惑

ludongxing
ludongxing 10月11日 字数 561

-1的补码为11111111(8个1),那么我要算(-1)+(-1),

就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

这个和的补码,再从这个和的补码得到原码的结果,这个原码

的结果就是我想要的最终结果,对吧?

那么,11111111+11111111(8个1加上8个1),就得到

111111110,一共是八个1和一个0,一共是9位,对吧?那么,

最左边的1不就是溢出了吗?使用一个8位的寄存器来做加减法,

而我得到了9位,第9位(最高位)必须扔掉,因为没有地方储存,

请问这个(-1)+(-1)的计算过程叫做产生溢出了吗?如果是

溢出的话,那么,汇编程序就无法计算(-1)+(-1)了吗?

汇编程序是这样写的:

mov AL, -1

add AL, -1

Programming 编程技术
20 个回复
GoGoRoger
GoGoRoger 10月11日

傻孩子,本来就是这么设计的,当然不是溢出,(-128)+(-1)才是溢出

发自「今日水木 on Mi Note 3」

【 在 ludongxing 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: 的结果就是我想要的最终结果,对吧?

: 那么,11111111+11111111(8个1加上8个1),就得到

: 111111110,一共是八个1和一个0,一共是9位,对吧?那么,

: 最左边的1不就是溢出了吗?使用一个8位的寄存器来做加减法,

: 而我得到了9位,第9位(最高位)必须扔掉,因为没有地方储存,

: 请问这个(-1)+(-1)的计算过程叫做产生溢出了吗?如果是

: 溢出的话,那么,汇编程序就无法计算(-1)+(-1)了吗?

: 汇编程序是这样写的:

: mov AL, -1

: add AL, -1

: --

fanci
大葡萄 10月11日

其实不是八个1,而是首位为1代表左边有无数个1,所以并没有溢出。

【 在 ludongxing () 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: 的结果就是我想要的最终结果,对吧?

a0123456789q
a0123456789q 10月11日

这个不叫溢出 而叫 精简。左边的1 相当于 01 中的0

【 在 ludongxing 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: ...................

a0123456789q
a0123456789q 10月11日

其实只需检查有没有变号就可以了。

【 在 ludongxing 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: ...................

ludongxing
ludongxing 10月11日

您说只要检查有没有变号就可以了,那来看这个情况:

要计算127-1,127的补码是01111111,-1的补码是

11111111。那么要算127-1等于几,就必须先算127

的补码加上-1(负1)的补码,然后再用这个和的补码

来算原码,这个原码就是应该等于正的126,对吧?

127的补码加上-1(负1)的补码应该是01111111+11111111,

所以,

01111111

+ 11111111

=101111110

那么,你说的“只需检查有没有变号就可以了”,在这里,

是应该变号还是不变号?别用人类的肉眼看127-1=126,别用

肉眼来判断有没有变号,如果是机器自己来判断,到底该不该

变号?

(-1)+(-1)用补码来算应该是这样:

11111111

+ 11111111

=111111110

到底以上的两种情况127-1和(-1)+(-1)都有没有溢出,

到底怎么判断有没有溢出?

【 在 a0123456789q 的大作中提到: 】

: 其实只需检查有没有变号就可以了。

a0123456789q
a0123456789q 10月11日

哦,我说的那是同号相加的情况;异号的是trivia case。如果非要说全:

1) 两个异号的必不溢出。

2) 两个同号的只需检查结果的符号有没有变。

【 在 ludongxing 的大作中提到: 】

: 您说只要检查有没有变号就可以了,那来看这个情况:

: 要计算127-1,127的补码是01111111,-1的补码是

: 11111111。那么要算127-1等于几,就必须先算127

: ...................

a0123456789q
a0123456789q 10月11日

其实 理解补码,可以从 借助 同模 加法理解。

【 在 a0123456789q 的大作中提到: 】

: 哦,我说的那是同号相加的情况;异号的是trivia case。如果非要说全:

: 1) 两个异号的必不溢出。

: 2) 两个同号的只需检查结果的符号有没有变。

: ...................

eGust
十年 10月11日

既然提到了 x86 汇编,那你应该知道有 overflow flag 跟 carry flag 是干这事儿用的啊

【 在 ludongxing (ludongxing) 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: ...................

a0123456789q
a0123456789q 10月11日

这是为什么 2's complement相对于1's complement而被采用的原因:有理论支持。

【 在 a0123456789q 的大作中提到: 】

: 其实 理解补码,可以从 借助 同模 加法理解。

ludongxing
ludongxing 10月11日

127的补码加上-1(负1)的补码应该是01111111+11111111,

所以,

01111111

+ 11111111

=101111110

现在先不考虑溢不溢出,如果有一个无限大的寄存器可以放下一万位(bit),

那么,这个和的结果(101111110)最左边的1要不要保留,如果保留,那么

这个结果就是负数了,对吧?

-127(负127)的补码加上-127(负127)的补码应该是10000001+10000001,

所以,

10000001

+ 10000001

=100000010

现在先不考虑溢不溢出,如果有一个无限大的寄存器可以放下一万位(bit),

那么,这个和的结果(100000010)最左边的1要不要保留,如果保留,那么

这个结果就是负数了,如果不保留,那么这个结果就是正数了,对吧?

到底做运算的时候,运算结果的最左边(最高位)的数字该不该保留?

【 在 a0123456789q 的大作中提到: 】

: 哦,我说的那是同号相加的情况;异号的是trivia case。如果非要说全:

: 1) 两个异号的必不溢出。

: 2) 两个同号的只需检查结果的符号有没有变。

: ...................

ludongxing
ludongxing 10月11日

我现在正在看王爽的《汇编语言》第四版的224页到225页,就是在学习OF(over flow)

标志寄存器(flag)和cmp指令。就是搞不明白,到底怎么判断发生溢出了和没发生溢出。

到底计算机是使用了什么标准来判断溢出有没有发生?

【 在 eGust 的大作中提到: 】

: 既然提到了 x86 汇编,那你应该知道有 overflow flag 跟 carry flag 是干这事儿用的啊

eGust
十年 10月11日

你搞反了,直接在运算的时候就直接设好 flag 了,并不是做完运算之后再去判断

这里有个小游戏,前几关就会用逻辑门实现加法运算,非常直观:

http://nandgame.com/

【 在 ludongxing (ludongxing) 的大作中提到: 】

: 我现在正在看王爽的《汇编语言》第四版的224页到225页,就是在学习OF(over flow)

: 标志寄存器(flag)和cmp指令。就是搞不明白,到底怎么判断发生溢出了和没发生溢出。

: 到底计算机是使用了什么标准来判断溢出有没有发生?

: ...................

ludongxing
ludongxing 10月11日

能不能先不看小游戏,针对127+(-1)和(-1)+(-1)这两个问题来

谈谈怎么判断溢出有没有发生?

【 在 eGust 的大作中提到: 】

: 你搞反了,直接在运算的时候就直接设好 flag 了,并不是做完运算之后再去判断

: 这里有个小游戏,前几关就会用逻辑门实现加法运算,非常直观:

http://nandgame.com/

: ...................

eGust
十年 10月11日

真是对牛弹琴啊,明明几分钟就能搞明白那俩 flag 是怎么来的了,笨一点半个小时也能做出来加法运算了,非得浪费时间琢磨不存在的问题。

overflow flag 针对 signed int,所以只是一个记录符号位变化的 flag 而已

【 在 ludongxing (ludongxing) 的大作中提到: 】

: 能不能先不看小游戏,针对127+(-1)和(-1)+(-1)这两个问题来

: 谈谈怎么判断溢出有没有发生?

a0123456789q
a0123456789q 10月11日

当然都不保留啊(你想保留也存不下啊)。

不保留后:

对于你说的第一个, 结果是正确的啊

对于第二个,结果是溢出错误。

判断程序就是我前面说的;其正确性保证就是我前面说的理论。

【 在 ludongxing 的大作中提到: 】

: 127的补码加上-1(负1)的补码应该是01111111+11111111,

: 所以,

:   01111111

: ...................

xiaoju
可爱的龙猫 10月11日

你这些问题,书上写的很清楚啊

小时候认得字少很是费了一番力气,后来语文过关了就能读懂了

【 在 ludongxing 的大作中提到: 】

: -1的补码为11111111(8个1),那么我要算(-1)+(-1),

: 就先得用-1(负1)的补码加上-1(负1)的补码,然后得到

: 这个和的补码,再从这个和的补码得到原码的结果,这个原码

: ...................

ArchLinux
a lightweight and flexible distribution 10月11日

有没有溢出这件事的判断是硬件做的。例如我可以用一个16bit的加法器,我把两个加数都符号扩展到16位相加,然后看得到的16bit结果在不在8bit有符号数的表示范围之内,不在的话就溢出了。

【 在 ludongxing (ludongxing) 的大作中提到: 】

: 我现在正在看王爽的《汇编语言》第四版的224页到225页,就是在学习OF(over flow)

: 标志寄存器(flag)和cmp指令。就是搞不明白,到底怎么判断发生溢出了和没发生溢出。

: 到底计算机是使用了什么标准来判断溢出有没有发生?

: ...................

cybereagle
2/3的沉默@XMUCSD 10月11日

你为什么计算的时候只用8位的寄存器

放结果的时候就要拿个1万位的寄存器?

你知道-1在1万位的寄存器里怎么写吗?

【 在 ludongxing (ludongxing) 的大作中提到: 】

: 127的补码加上-1(负1)的补码应该是01111111+11111111,

: 所以,

:   01111111

: + 11111111

: =101111110

: 现在先不考虑溢不溢出,如果有一个无限大的寄存器可以放下一万位(bit),

: 那么,这个和的结果(101111110)最左边的1要不要保留,如果保留,那么

: 这个结果就是负数了,对吧?

: -127(负127)的补码加上-127(负127)的补码应该是10000001+10000001,

: 所以,

:   10000001

: + 10000001

: =100000010

: 现在先不考虑溢不溢出,如果有一个无限大的寄存器可以放下一万位(bit),

: 那么,这个和的结果(100000010)最左边的1要不要保留,如果保留,那么

: 这个结果就是负数了,如果不保留,那么这个结果就是正数了,对吧?

: 到底做运算的时候,运算结果的最左边(最高位)的数字该不该保留?

littleSram
littleSram 10月11日

这游戏有意思

【 在 eGust 的大作中提到: 】

: 你搞反了,直接在运算的时候就直接设好 flag 了,并不是做完运算之后再去判断

: 这里有个小游戏,前几关就会用逻辑门实现加法运算,非常直观:

http://nandgame.com/

: ...................