1735485012 发表于 2013-11-2 16:30:03

关于有符号数,无符号数的问题

如果在debug下输入
mov al,f0
addal,88

计算机会把f0和88,由16进制转化为二进制补码的形式存放在cpu中,那么cpu怎么判断
f0 和88是有符号数还是无符号数呢,具体的转换及运算过程能详细讲解一下吗?
小女子感激不尽

1735485012 发表于 2013-11-2 16:45:46

是不是我们输入的数,计算机都会转成二进制补码的形式存放起来?

一匹神奇的狼 发表于 2013-11-2 17:11:10

输入的数都会按照机器码表示,只不过要看你怎么解释它。比如说,0xff可以解释为-1也可以解释为255。你可以深入理解一下机器码

福禄娃娃 发表于 2013-11-2 22:05:02

本帖最后由 福禄娃娃 于 2013-11-2 22:20 编辑

由于-128的原码用8位无法表示,所以必须扩展到16位去表示,然后对16位的原码计算出16位的反码和补码,最后对16位的补码作低8位的截断,截断的低8位的值就是-128的补码了。// 8位所能表示的原码 的范围-127到+127
// 8位所能表示的反码 的范围-127到+127
// 8位所能表示的补码 的范围-128到+127

// 计算机当中,是规定-128的补码是1000 0000
// 算的时候则需要扩展到16位来算。否则,第8位到底表示符号还是表示数值2的7次方呢?所以,8位就按8位的通常看法来看, -128的补码是1000 0000
// 是难以理解的。只能扩展后来看。

// -128原码 1000 0000 1000 0000
// -128反码 1111 1111 0111 1111
// -128补码 1111 1111 1000 0000

// -129原码 1000 0000 1000 0001
// -129反码 1111 1111 0111 1110
// -129补码 1111 1111 0111 1111

int main(int argc, char* argv[])
{
    char ch = -129; // warning C4309: 'initializing' : truncation of constant value
    char ch2 = -128; // no warning
    return 0;
}

注意:由于char能表示的范围是:-128~127,如果将-129赋给char,编译的时候是会产生warning的,并会截断,截断后的值是0x7f(127)。

1735485012 发表于 2013-11-2 23:29:43

福禄娃娃 发表于 2013-11-2 22:05 static/image/common/back.gif
由于-128的原码用8位无法表示,所以必须扩展到16位去表示,然后对16位的原码计算出16位的反码和补码,最后 ...

恩,还有个问题

在debug 下输入一个数例如f0,那么cpu 是认为它是有符号的还是无符号的呢?
它在内存中的存储数据是多少?

福禄娃娃 发表于 2013-11-2 23:46:38

1735485012 发表于 2013-11-2 23:29 static/image/common/back.gif
恩,还有个问题

在debug 下输入一个数例如f0,那么cpu 是认为它是有符号的还是无符号的呢?


CPU不知道内存中的数据到底是什么类型的。

实际上内存中的数据就是没有类型的,你想怎么存就怎么存(不过要区分小尾和大尾方式),想怎么理解就怎么理解。

有符号整型最高位代表符号位,而无符号整型最高位仍然用来表示整数的一部分。

这就是为什么同样字节数的存储空间,无符号整型的可表示最大正值是有符号整型最大正值两倍+1的原因,如无符号8位最大可以表示1111 1111即255,而有符号因为最高位要表示符号,所以最大正值为0111 1111即127。

程序最终到了处理器级别就不知道内存中的数据到底是什么类型了,有所不同的是处理机执行的指令(OPCode)一厢情愿地把内存中的数据当成对应的数据类型在用而已。如果你知道处理机执行的指令,又知道它要访问的内存地址,你就可以人为地修改这些地址中的数据来达到你要的效果。缓冲区溢出也就是这样被利用的。

由于无符号数的加法与有符号数(补码)的加法是一致的,因此完全没有必要去区分指令的操作数是有符号数还是无符号数。关键在于运算结果你自己如何看待。
例如:
  al=1001 1100(9C),bl=1110 0111(E7),则
  add al,bl 
  运算结果是:
  al=1000 0011(83) 且进位标志CY=1,溢出标志OV=0.

  对于这个结果,你可以把它作为无符号数运算,即有:
  al=9Ch=156d,bl=E7h=231d,运算结果al=83h=131d,考虑到进位,运算结果应为131+256=387,而al+bl=156+231=387.正确。

  同样对于这个结果,你也可以把它作为有符号数的运算,即有:
  al=9Ch=-100d,bl=E7h=-25d,(注意有符号数均看成补码,9Ch是-100的补码,下同)。
  而运算结果al=83h= -125d,因为没有溢出(有符号数是不考虑进位的),运算结果可用。
  而al+bl=9Ch+E7h=(-100)+(-25)=-125.可见结果亦完全正确。

  由上例可见,无符号数的加法与有符号数的补码加法是完全一致的。CPU没有必要去区分。关键在于程序员如何去看待。CPU的运算结果将同时影响进位标志与溢出标志。如果程序员认为这是无符号数运算,则只考虑进位标志而忽略溢出标志。反之,如果程序员认为这是有符号数运算,则只考虑溢出标志而忽略进位标志。

1735485012 发表于 2013-11-3 07:22:32

福禄娃娃 发表于 2013-11-2 23:46 static/image/common/back.gif
CPU不知道内存中的数据到底是什么类型的。

实际上内存中的数据就是没有类型的,你想怎么存就怎么存(不 ...

多谢你了,说的很详细

1735485012 发表于 2013-11-3 08:35:44

福禄娃娃 发表于 2013-11-2 23:46 static/image/common/back.gif
CPU不知道内存中的数据到底是什么类型的。

实际上内存中的数据就是没有类型的,你想怎么存就怎么存(不 ...

“al=9Ch=-100d,bl=E7h=-25d,(注意有符号数均看成补码,9Ch是-100的补码,下同”

意思就是说,我们输入的16进制数,计算机是直接转换位二进制,当做补码直接存储在内存单元中的,是这个意思吧?

我之前想的是,计算机再计算出 这个16进制数的补码,然后再存储,我想的是错的
页: [1]
查看完整版本: 关于有符号数,无符号数的问题