1、原码、反码、补码知识的复习:

三者的高位均为符号位。我以前一直没弄明白的是为何8位补码的表示范围是-128~127,今天查阅了相关资料,于此记下。

仍然以8位为例:

原码的表示范围:-127~-0,+0~+127,共256个数字。正0的原码是0000 0000,负0的原码是:1000 0000,有正0负0之分,不符合人的习惯,待解决。

反码:除符号位,原码其余位取反而得。+0:0000 0000,-0:1111 1111仍然有正0负0之分。

补码:在反码的基础上加1而得。对原码的两种0同时末位加1。+0:0000 0000,-0:0000 0000(因为溢出导致8位全0)。消除了正0负0之别,如此一来,便节省出一个数值表示方式1000 0000,不能浪费,用来表示-128。-128特殊之处在于没有相应的反码原码。也可以这样考虑:

-1:   1111 1111

-2:   1111 1110(在-1的基础上减1,直接将补码减1即可)

-3:   1111 1101(在-2补码基础上减1,以下类似)

-4:   1111 1100

……

-127:1000 0001

-128:1000 0000

如此以来:8位补码表示范围是-128~+127因为0只有一种形式所以,仍然是256个数,若8位代表无符号数,则表示范围是:0~255,这就是为什么高级语言讲到数据类型,比如C++中的short类型时(16位长)说其表示范围是:-32768~+32767,而unsigned short表示的范围则是:0~65535

2、关于无符号数和有符号数:

无符号数及有符号数的定义就不多说了,任何计算机基础书籍都会讲到。

二者的区别:我们知道,有符号数在计算机中以补码的形式存储,无符号数其实就是正数,三码一致,存储形式即是其十进制真值对应的二进制数。所以可以这样说,无论有符号数还是无符号数,都是以补码(相对真值来说)的形式来存储的,补码在运算是符号位也会参与。

其实对计算机来说,它根本没有所谓的无符号有符号这样的约定机制,无符号有符号只不过是我们(程序员、学习者)看待二进制数据的方式,比如,对于16位的寄存器(比如ax)有符号数-1的存储形式是0FFFFH(即16个1,-1的补码,最高位符号位),而同时无符号数65535的存储形式也是0FFFFH。所以对计算机来说,它仅仅是存储了一串二进制,至于是有符号数还是无符号,你程序员要心中有数。C++代码举例:

short a=-1;
unsigned short b=a;
cout<<a<<endl;//打印有符号数-1,对应存储形式0FFFFH
cout<<b<<endl;//打印无符号数65535对应存储形式0FFFFH

3、汇编相关

已经说过,数据以补码形式存储于计算机中(有符号、无符号),自然,寄存器,比如ax,存的也是补码,比如:mov ax,-96,查看便知ax存储的是0FA0H。在高级语言编程中,我们完全不用考虑什么原码补码。汇编的add指令在运算时,比如

mov al,0

add al,-1

它不去“考虑”什么有符号无符号,反正数据都以补码(无符号数据便是正数,补码不变)的形式存储、运算,它只管将al中的补码与99的补码加一起然后存入al中(补码的运算特点是:符号位也参与运算),我们知道运算后al存储的是1111 1111(0FFH),至于你如何看待这个结果,由你程序员控制,你看成有符号数它便是-1,看成无符号数它便是255。

与此同时,相关的寄存器也会有相应的机制,来配合编程人员。比如标志寄存器中的SF标志位,如果编程人员将数据看成无符号数,则我们SF对我们是毫无意义的——尽管对我们毫无意义,但计算机依然以“有符号数”的态度来“看待”参与运算和存储的数据,比如

mov ax,12

add ax,-18

结果为负,sf=1(结果如果为非负,则sf=0)

计算机不管编程人员以什么眼光(有符号无符号)来看待数据,反正它把所有的可能都考虑到了,把相应的工作也做了,编程人员可按需而来。不妨想象一种情景:假如计算机完全以无符号数来看待数据,压根没有sf标志位,那么如果程序员想知道某数据的正负(以有符号数来看待数据)时,便无从下手了。

可以说,计算机仁至义尽,剩下的便是程序员的事了。

4、汇编中的CF、OF、SF标志位及cmp操作

CF对无符号数运算是有意义的,OF,SF对有符号数而言是有意义的。ZF则都适用。

一个是进位借位标志位一个是溢出标志位,溢出是指:在进行有符号数运算时,结果超过了机器所有表示的范围(五爽《汇编语言》),可知,OF只对有符数运算有意义,无符号数不关心这种溢出。无符号数关心的是最高位向更高位借位进位问题。(从这个层面上来讲,其实也可将这种向更高位借位进位看成无符号数的“溢出”)。所以CF只对无符号数的运算有意义,即当考虑CF标志位的时候要做到心中有数:现在参与运算的都是无符号数——这依然是程序员的事。

可能会有这样的疑问:两个数运算,如果溢出了,那么以“无符号的眼光”看来,不也是产生了借位或者进位吗?或者反之,两个数运算,如果进位或者借位了,那么以”有符号的眼光“看来,不也是产生了溢出吗?

对于第一个问题:不一定,比如0111 1111+0000 0001,看成有符号数运算的话,结果明显溢出,但如果看作无符号的运算的话并没有向更高位(无符号数无符号位,均为数值位)进位。

又如:mov al,98 add al,99(即0110 0010+0110 0011)运算后CF=0,OF=1。具体的过程可以这样考虑:

首先,用的是al来运算,所以计算机知道做的是8位运算,加得结果:1100 0101,对于无符号来说无进位,CF=0,对于有符号来说溢出了:OF=1.

对于第二个问题:也不一定。如:

mov al,0F0H

add al,88H执行后CF=1,OF=1,但是,请看另一例:

mov al,0F0H

add al,78H

对于0F0H和78H,首先要明白,如果看作无符号数,则便是240+120,明显会在高位向更高位产生进位,所以CF=1,如果看作有符号数,作为人类的程序员,有两种方式可以判定是否溢出:

a、将0F0H和78H(补码)转换成10进制数值(按照符号位不变其余位取反然后末位加1转成原码,再求),相加看是否在-128~127之内。也可按补码求真值的公式直接求出补码对应的真值:真值x=-2^n*xn+其余各位2进制对应真值。其中xn为最高位即符号位,为0或者1。

b、单符号判溢出方法:这是组成原理(白中英主编第4版)介绍的判断溢出的方法,补码相加,看符号位及最高有效位。将16进制的补码转换成2进制:1111 0000和0111 1000,相加:

1111 0000

0111 1000

可看出最高有效位有符号位均产生了进位,这种情况不视为溢出(只有二者之一产生进位时才算溢出)。

 

有符号数的溢出问题引发了cmp操作的相关问题。

cmp是比较指令,相当于减法,但不会将结果保存在目的操作数中,但会影响标志位sf,zf,cf。利用它既可以对无符号数比较也可以对有符号数进行比较。至于是有符号数还是无符号数,这依然取决于我们的看待方式,如:

mov ax,8

mov bx,3

cmp ax,bx

看成无符号数分析:因为无须借位,cf=0(据此可以判断ax>bx),因为结果不为0,zf=0(据此可以判断ax bx是否相等)

对于有符号数,情况要复杂一些,因为牵扯到了溢出问题。

比如已知(ah)=22H,(bh)=0A0H,二者都是补码,一个为正一个为负,二者对应的真值分别为:34和-96,逻辑上讲(ah)>(bh),但cmp ah,bh运算时会溢出:34-(-96)=-230,小于-128。另外,我们可以直接用16进制减法手动计算结果:

22

A0

---------

82H,即1000 0010,知结果为-1*2^7+2=-126,这显然是个错误的结果。计算机不会进行减法,它得转成加法。用补码加法计算有个好处,可用上边已经介绍过的单符号位判溢出方法判断结果是否溢出。过程:x补=22H=0010 0010,y补=1010 0000,求x补-y补,这是补码减法,转换成加法:x补-y补=x补+[-y]补,由y补求[-y]补:包括符号位全部取反,然后末位加1(参照白中英组成原理课本相关内容),转变后即为:0010 0010+0110 0000,由单符号位判溢出方法可知,只有高位有效位产生了进位,进给了符号位,这是一个溢出,一个上溢。

要注意的是:引入补码带来的便处之一使得负数的加法转成补码的加法(负数的加法便是减法),但是如果不加控制补码之间也会进行减法,此时也要将相应的减法转成加法运算,当然这种转换的工作不是我们所做的,转换的原理如上所述。

因为溢出问题,导致上面cmp结果为负,sf=1,如果仅据此就说(ah)<(bh)明显是错误的,此时还要结合of位,因为有溢出,所以of=1(如果of等于0,说明没有溢出,则我们可以放心地使用sf来判断)。一条规律是:有溢出,则cmp结果与of表示的相反,本来打算验证一下,还是算了,抱着复习相关知识的心态,写了这么多,蛋疼。

 

  

 

转载于:https://www.cnblogs.com/qzhforthelife/archive/2012/10/30/2746918.html

无符号数、有符号数、补码在汇编中的运用及相关注意事项相关推荐

  1. 无符号数转化为有符号数

    计算机存储数据是以补码形式存储的. 一般来说,有符号数值使用补码表示,无符号的数值使用原码来表示,因为正数原码=补码,其实也是补码. 无符号数值只有正数.所以比如一个16位元可以储存的最大正数是2的1 ...

  2. 6.1无符号数和有符号数

    6.1无符号数和有符号数 1. 数据在计算机中的表示 数据表示是指在计算机当中.能够被硬件.直接识别和处理的数据类型 所谓能够被硬件直接识别和处理.是指在计算机系统的指令级中.包含对这些种类型的数据进 ...

  3. 如何判断一个数为无符号数还是有符号数

    方法一: 判断一个数是不是有符号数:首先判断这个数是不是小于零,小于零肯定是有符号数 然后根据无符号数和有符号数相减结果为无符号数 #include <iostream> using na ...

  4. c语言无符号整型右移,c语言 java 有符号数,无符号数. 左移,右移运算

    1: c语言区分有符号数,无符号数.有符号数是符号位在首位,无符号数首位就是普通位数. java只有有符号数,换句话说java二进制中首位都是符号位.0正1负. 2: 左移在所有语言中只是左移,不存在 ...

  5. 有符号数(signed) 和 无符号数(unsigned)

    我们在程序中看到的数字都是十进制值(加OX前缀或H后缀等修饰的数值除外),但在计算机底层它们都是以二进制的形式表示的.即用0和1来表示,对各种进制之间的转换不熟悉的可以看看,进制转换 和 举例说明 有 ...

  6. verilog 有符号数

    (1)在FPGA综合成电路的时候最底层都是以补码的形式在运算,正数的补码就是本身,负数的补码要取反+1. (2)编译器高的版本都支持verilog有符号运算的综合了.在定义时直接加上signed即可, ...

  7. Verilog 有符号数 signed

    首先记住,有符号数的运算全都是补码的方式. 在Verilog里面,可以使用有符号数据进行运算,定义时使用signed,例如 reg signed[7:0] adder: //定义了一个reg型有符号8 ...

  8. C#将16位二进制转换为有符号数

    //将双字节转换为有符号数. public int getValueFromUnSigned(byte bHight, byte bLow) { if (bHight < 128) return ...

  9. 汇编中各寄存器的作用(16位CPU14个,32位CPU16个)和 x86汇编指令集大全(带注释)

    From:https://www.cnblogs.com/zimmerk/articles/2520011.html From:https://blog.csdn.net/bjbz_cxy/artic ...

最新文章

  1. r语言 聚类求和_R语言聚类分析,如何导出将分类结果?
  2. 一些计算机知识的总结(转)
  3. SQL Server 2008获取一个表的字段,类型,长度,是否主键,是否为空,注释等信息...
  4. python中文件路径如何读取提示nosuch file_Python 解决相对路径问题:No such file or directory...
  5. 登录:应用程序错误通知
  6. mysql tomcat列表增删改查_Tomcat-Database
  7. Linux学习笔记-编译与链接的过程
  8. Visual Studio 2019预览,净生产力
  9. Delphi用指针读取数组某个元素
  10. 服务器每条消息都回复,如何理解PUSH消息送达成功率
  11. QT开发pjsip的VOIP,A8平台运行
  12. 手把手教你进行R语言的安装及安装过程中相关问题解决方案
  13. js基础知识汇总02
  14. MyEclipse使用总结——在MyEclipse中新建Maven框架的web项目[转]
  15. 怎么判断前轮左右的位置_老司机教你如何用方向盘,判断左右车轮位置,新手司机一看就会!...
  16. 黑客泄露澳大利亚大量求职者信息,其中包含11家重要公司名单
  17. 吊打全球的顶级毫米波数字阵列项目-MIDAS
  18. 订单管理_03查询订单信息流程
  19. js 公众号 获取code_微信公众号开发之网页授权登录及code been used 解决!
  20. Vue-router导航

热门文章

  1. Linux内核 TCP/IP、Socket参数调优
  2. Java Observer Pattern(观察者模式)
  3. ASIHTTPRequest源码简单分析
  4. 使用keepalived实现双机热备
  5. Centos6.3下DRBD+HeartBeat+NFS配置笔记
  6. WCF分布式开发常见错误(10):套接字连接中断,The socket connection was aborted
  7. PHP 利用Mail_MimeDecode类提取邮件正文
  8. android天气查询(二)之网络json数据的获取
  9. html-盒子模型及pading和margin相关
  10. ActiveMQ在windows下启动失败解决方案