补码详细分析和汇编下的使用

Posted congmingyige

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了补码详细分析和汇编下的使用相关的知识,希望对你有一定的参考价值。

原码,反码,补码

考虑范围:二进制8位整数,[-128,127]

():二进制数中的所有的0变为1;所有的1变为0

这里的01串默认为二进制

 

I.原码

把数的绝对值写成二进制的形式(7位),其中-128只取0000000

若数为非负数,则最高位(第八位)为0

若数为负数,则最高位(第八位)为为1

Ex:

72=2^6+2^3     01001000

-15=-(2^3+2^2+2^1+2^0) 10001111

 

II.原码与反码

正数:反码=原码

负数:在原码的基础上除最高位的数字“1”不变;其它位取反

反码=(原码-10000000)=11111111-(原码-10000000)

则 原码=11111111-反码=(补码)

 

III.原码与补码

正数:补码=原码

负数:在原码的基础上除最高位的数字“1”不变;其它位取反,再加1,如果有进位则忽略(原码10000000,则补码10000000)

除了10000000:

补码=(原码-10000000)+1

=11111111-(原码-10000000)+1

=100000000-(原码-10000000)

则 原码-10000000=11111111-补码+1=(补码)+1

   原码-10000000=11111111-(补码-1)=(补码-1)

   原码-10000000=100000000-补码

 

正数=原码=补码

负数=-(原码-10000000)=补码-100000000

即补码=负数+100000000

10000000同样满足负数=补码-100000000,补码=负数+100000000

 

.

:

1.正数(00000000~01111111):补码=正数=数%100000000

2.负数(-100000000~-00000001):

补码=负数+100000000=数%100000000

所以:补码=数%100000000

.

补码:

1.00000000~01111111:数=补码

2.10000000~11111111:数=补码-100000000

由一、二得,数与补码互相唯一决定对方

 

IV.补码加法

要求:

1.不溢出:即结果在-128~127范围内

2.第9位的进位忽略,即结果对100000000取余

 

x+y=z

补码:x‘+y‘=z‘(补码对应原码,即x‘,y‘对应x,y)(这里的等号不是传统意义上的加法)

证明z‘与z互相唯一决定对方

证明:

z‘=(x‘+y‘)%100000000=(x%100000000+y%100000000)%100000000

=(x+y)%100000000=z%100000000

得证

 

V.补码减法

要求:

1.不溢出:即结果在-128~127范围内

2.若第8位不够减,则第9位进行补位,即结果对100000000取余

 

x-y=z

补码:x‘-y‘=z‘(补码对应原码,即x‘,y‘对应x,y)(这里的等号不是传统意义上的加法)

证明z‘与z互相唯一决定对方

证明:

z‘=(x‘-y‘)%100000000=(x%100000000-y%100000000)%100000000

=(x-y)%100000000=z%100000000

得证

 

以下是汇编部分——

VI.补码加法的溢出判断

要求:第9位的进位忽略,即结果对100000000取余

正数对应的补码:00000000<=t<=01111111

负数对应的补码:10000000<=t<=11111111

 

z‘=x‘+y‘ (x‘,y‘,z‘的原码为x,y,z)

z‘对应z,两者的溢出状况相同,即两者同时溢出或不溢出。

 

1.x’最高位为0,y’最高位为1(x=非负,y=负)

原码:

x+y>=0+(-128)=128

x+y<=127+(-1)=126<=127

原码没有溢出,对应补码也不会溢出

 

2. x’最高位为0,y’最高位为0(x=非负,y=非负)

00000000<=x‘,y‘<=01111111,两者相加小于100000000,不会进位,z‘=x‘+y‘。

非负数+非负数,结果为非负数,非负数最大时对应的补码为01111111。

x‘+y‘大于等于10000000(80H),溢出;

x‘+y‘小于10000000(80H),不溢出。

 

3. x’最高位为1,y’最高位为1(x=负,y=负)

10000000<=x‘,y‘<=11111111,两者相加大于等于10000000,会进位,z‘=x‘+y‘-100000000。

负数+负数,结果为负数,负数最大时对应的补码为10000000。

x‘+y‘-100000000小于10000000(80H),溢出;

x‘+y‘-100000000大于等于10000000(80H),不溢出。

 

VII.补码减法的溢出判断

要求:第9位的借位忽略,即结果对100000000取余

正数对应的补码:00000000<=t<=01111111

负数对应的补码:10000000<=t<=11111111

 

z‘=x‘-y‘ (x‘,y‘,z‘的原码为x,y,z)

z‘对应z,两者的溢出状况相同,即两者同时溢出或不溢出。

 

1.x’最高位为0,y’最高位为0(x=非负,y=非负)

原码:

x-y>=0-127=-127>=-128

x-y<=127-0=127

原码没有溢出,对应补码也不会溢出

 

2.x’最高位为1,y’最高位为1(x=负,y=负)

原码:

x-y>=(-128)-(-1)=-127>=-128

x-y<=(-1)-(-128)=127

原码没有溢出,对应补码也不会溢出

 

3. x’最高位为0,y’最高位为1(x=非负,y=负)

00000000<=x‘<=01111111,10000000<=y‘<=11111111,两者相减小于0,会借位,z‘=x‘-y‘+100000000。

非负数-负数,结果为非负数,非负数最大时对应的补码为01111111。

x‘-y‘+100000000大于等于10000000(80H),溢出;

x‘-y‘+100000000小于10000000(80H),不溢出。

 

4. x’最高位为1,y’最高位为0(x=负,y=非负)

10000000<=y‘<=11111111,00000000<=y‘<=01111111,两者相减大于0,不会借位,z‘=x‘-y‘。

负数-非负数,结果为负数,负数最大时对应的补码为10000000。

x‘-y‘小于10000000(80H),溢出;

x‘-y‘大于等于10000000(80H),不溢出

 

 

总结:补码的结果必然为负数和非负数的其中一类。当运算溢出,数超出了负数/非负数的范围[即若结果为负数,补码小于80H;若结果为非负数,补码大于等于80H],到达非负数/负数,即逻辑上真正的结果与实际结果相反。

 

sf:实际上是进行补码运算,即z‘=(x+/-y)%100000000,当z‘的最高位为1,即负,sf=1;当z‘的最高位为0,即非负,sf=0。(这样记忆就好了!)

cf:在无符号数运算中有进位或借位,cf=1;否则cf=0

of:进行有符号数运算,若溢出(超出[-128,127]),of=1;否则of=0

 

cmp x,y

对于x-y的结果:

I.当sf=1,of=0:没溢出,即结果为负数(sf),x<y。

II.当sf=1,of=1:溢出,即结果为非负数(非sf)。即为非负数-负数,所以不存在相等的情况。x>y。

III.当sf=0,of=0:没溢出,即结果为非负数(sf)。等号可以成立,当x=y时成立。x>=y。

IV.当sf=0,of=1:溢出,即结果为负数(非sf),x<y。

 

以上是关于补码详细分析和汇编下的使用的主要内容,如果未能解决你的问题,请参考以下文章

汇编语言第一节课:数制转换,真值和补码

DOSbox汇编集成环境下的详细设置

用汇编语言减去 16 位 2 的补码

JVM优化之循环展开(附有详细的汇编代码)

LINUX下GDB反汇编和调试

求补码一位乘(booth乘法 比较法)计算x=11011y=-11111求x*y的详细过程