怎么区分有符号数和无符号数

来源:互联网 发布:淘宝介入对卖家不公平 编辑:程序博客网 时间:2024/05/02 02:49

转载至:http://www.myexception.cn/program/1264261.html

我还是搞不清指令本身是如何区分有符号数和无符号数!(问题汇总)

论坛的一个CSDN提问,对各方面的回答进行了汇总,答案还算比较清楚的。

 

一般好像是有专门的有符号数指令和无符号数指令
比如
无符号除法是 div
有符号除法是 idiv

 

mov al,27h
mov bl,73h
add al,bl

27h   00100111
73h   01110011

如果是无符号数al的结果为10011010(9A),如果是有符号数结果是什么?

答:
    如果是有符号数,结果依然是10011010(9A)。注意,此时溢出标志置位。表明这个加法如果是作为有符号数的加法时,结果是不能用的。当然,如果你把这个加法作为无符号数的加法来看,结果则是可用的(虽然此时仍有溢出,但它是无意义的。溢出只针对有符号数而言的)。
    这是个特例。因为无符号数的加减法与有符号数的补码的加减法是恰巧是一致的。因此有符号数与无符号数可以使用同一指令,得到同一结果。而这一结果是作为有符号数还是无符号数,是由程序员来定义的:如果程序员认为是有符号数的加减法,则他将关心运算结果的溢出标志,以判别结果是否可用;如果程序员认为是无符号数的加减法,则他将关心运算结果的进位标志,看运算结果是否有进(借)位。
    正是基于这样的原因,计算机的有符号数才采用补码表示。

 

上面不是跟你说的很清楚了吗?由于无符号数的加法与有符号数(补码)的加法是一致的,因此完全没有必要去区分指令的操作数是有符号数还是无符号数。关键在于运算结果你自己如何看待。
例如:
  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的运算结果将同时影响进位标志与溢出标志。如果程序员认为这是无符号数运算,则只考虑进位标志而忽略溢出标志。反之,如果程序员认为这是有符号数运算,则只考虑溢出标志而忽略进位标志。

 

指令本身不区分操作数的类型。
指令的操作格式是固定的,并对应一个操作码。

在 C 下,应该是由编译器根据你定义的数据类型使用不同的指令。
汇编下,你应该去选择使用那类指令。

 

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

高级语言,如c语言有符号数和无符号数在内存的储存上没什么不同
关键是处理数的指令,如果你声明的是有符号数,编译器在编译时就用有符号数的机器指令
反之就用无符号数的机器指令
而汇编语言中这些就要你自己来做了

总结一下,想了半天。
1.
同意zhukeke(zhukeke)的: "有符号数与无符号数从静态的二进制来看,是无区别的。指令之所以能区别,则是指令的设计者总是事先规定它的操作数的类型。"
但有些指令除外,象add这条,有符号数与无符号数公用,都会影响CF,OF,OF,ZF,PF.CPU统一对待.在于你怎么看待.
2.关于add指令:
(基于:(1)运算器(加法器)只有一个逻辑,无论什么运算都一样.(2)存储字长的有限.)
既然add指令有符号数与无符号数公用,都会影响CF,OF,OF,ZF,PF.为什么无符号数关心CF位,有符号数关心OF位??这其实是有符号数的表示方法即补码惹的"祸".无符号数在字长不够时,可用CF位来寄存一位,从而解决不够问题.而有符号数确不能简单利用CF位.因为负数的补码的表示问题.

比如:al=1111 1111B与bl=1000 0000B.当add al,bl时.CF=1,OF=1.表示进位,溢出.
==看成无符号数,当然也是进位,溢出了.但无符号数只需利用CF位即可修正:.因为结果在16位表示为00000001 01111111,32位为0000000000000000 0000 000101111111 ,总之高位为0,用0111 1111和进位位就能表示正确结果(CF+al),所以大家只关心CF位了.OF位不关心了!
==看成有符号数,当然也是进位,溢出了.但有符号数不能简单利用CF位修正.实际上不好修正.因为结果为al(-1)+bl(-128)=al(-129) -129的补码表示在16位为:11111111 01111111.在32位为:1111111111111111 11111111111101111111.总之,高位全为1.用CF位无法修正.位数不够.有人说高位全置1,不就OK??可al只有8位啊,所以光用CF+al是不行的.所以只能说它溢出了.不能用这个结果了.所以只关心OF位了.

站在计算机组成的角度,这个问题是不存的:指令是由硬件电路识别(译码)完成的,详细的解释见组成原理。这一层是在微命令层次完成的,不能完成微命令的“码”就是地址码!(IBM),而地址码是指明数据位置的或计数的
如果是用汇编者眼光分析,问题在于你的指令已经识别出来------指令池中有这些“硬件库”。其它的“码”均视为数据(内存中的单元的地址或一个数据),它的构造由你程序决定:有符号还是没符号。这里还是要从组成原理角度才能说清。
如果你使用的是高级语言,则几乎没有必要对它进行讨论,因为指令在高级语言(如C)中是透明的。

0 0
原创粉丝点击