什么是有符号数?什么是无符号数?什么是溢出(OF)?什么是进位(CF)?如何区分有无符号 呢?
有符号数,就是带符号的数,可以是正数或负数。区分正数或负数时,看这个数的最高位是 否为 1,最高位为 1,说明它是负数。最高为 0 说明它是正数。
例如
一个字节有符号数,表示范围(-128 ~ 127):
A0 :1010 0000 : -96 最高位为 1,说明是负数 80 :1000 0000 :-128 最高位为 1,说明是负数 5B :0101 1011 : 91 最高位位 0,说明它是正数 09 :0000 1001 : 9 最高位位 0,说明它是正数
两个字节有符号数,表示范围(-32768 ~ 32767):
A055: 1010 0000 0101 0101 :-24491 201A: 0010 0000 0001 1010 :8218 35B9: 0011 0101 1011 1001 :13753
最高位为 1,说明是负数 最高为 0,说明它是正数 最高为 0,说明它是正数
现在我们对于有符号数有了了解,那么无符号数呢? 无符号说明这个数是没有符号的,那么它的最高位将会变成有效位。不会再用来检查是否正 负数。
一个字节无符号数,表示范围(0~ 256): A0:1010 0000 :160
BE:1011 1110 :190
90:1001 0000 :144
50:0101 0000 :80
两个字节无符号数,表示范围(0~ 65536): EA00: 1110 1010 0000 0000 : 59904 8000: 1000 0000 0000 0000 : 32768 0900: 0000 1001 0000 0000 : 2304
0080: 0000 0000 1000 0000 :128
可以发现无符号数就是正数,没有负数,范围就非常的大。
现在了解了有符号和无符号数,接下来继续理解什么是溢出!
溢出:当有符号位超出它的表示范围就算溢出。
用个例子来表示(1 个字节加法):
0x80 + 0x9F = 0x(1)1F 最终结果等于 0x1F(31)
上面的例子非常明显,十六进制0x80是十进制-128, 十六进制0x90是十进制-112 那么他们 相加结果是应该-240,-240 已经超过 1 个字节有符号数(-128~127)的表示范围了,结果明
显是错误的。此时我们就可这两个数相加就算溢出。 再用一例子来表示(1 个字节减法):
0x80 – 0x46 = 0x3A 结果等于 0x3A(58)
明显结果是错误的,十六进制 0x80 是十进制-128,十六进制 0x46 是十进制 70, (-128 )– ( 70 )= -198 结果应该是一个负数,而且这个数明显已经超过 1 个字节有符号数(-128~127) 的表示范围了,这也是溢出。
现在大致明白了什么是溢出,总结一下有这种规律:
当两个有符号数进行运算时,符号位不同时,相加或相减不可能溢出。
只有在符号位相同情况,进行运算下才会溢出。
什么是进位? 对于进位来说,在无符号进行运算时才会产生进位(加法)或者借位(减法)。
举个例子(1 个字节):
0xEA +0x55 = 0x(1)3F 结果大于无符号(0-256)所能容纳的范围,产生进位(CF=1)。 0x10 – 0x14= 0xFC 结果由于被减数小于减数,此时就会产生借位(CF=1)
到此我们应该能理解什么是溢出?什么是进位(借位)?
但是可能会有人问,那我在汇编中计算一个值,我怎么知道它是有符号,还是无符号,有该 怎么去区分呢?
答案是:没有区分,或者说你当它有符号可以,无符号也可以。 在看一个例子:
0x80 + 0x8F = 0x(1)0F
这个例子中相加后结果即产生了进位,又产生了溢出。
CF =1 ,OF =1;
所以 CPU 不区分有符号或者无符号,它在计算时都当成有符号进行计算,根据结果设置标 志位。
区分有符号,或无符号是汇编指令。或者说是你决定的。
C 中有 unsigned 与 signed 来确定有无符号。
汇编中有写指令区分有无符号。
原文地址:http://blog.51cto.com/haidragon/2097432