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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/302079.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WPF Treeview第三层横向排列

WPF 第三级横向排列效果&#xff0c;左侧使用WrapPanel&#xff0c;右侧使用StackPanel,效果见下图&#xff1a;代码如下&#xff1a;Mainwindow的xaml如下:<Window x:Class"WPFDemos.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presen…

联想 android 5.1 root权限,联想A520手机ROOT权限图文教程(附联想A520root工具)

联想A520 ROOT教程&#xff1a;2、将手机USB调试打开;步骤&#xff1a;设置----应用程序----开发-----USB调试设置----应用程序----未知源&#xff0c;后面的勾打上就行;3、打开了USB调试和未知源之后&#xff0c;双击联想A520 ROOT.exe&#xff0c;将它安装到电脑端;安装好后打…

入门深度学习,其实并不难!

深度学习的概念源于人工神经网络的研究&#xff0c;而深度学习的过程就是使用多个处理层对数据进行高层抽象&#xff0c;得到多重非线性变换函数的过程。虽然深度学习的概念看似高大上&#xff0c;让人有种莫名的距离感&#xff0c;实际上它在日常生活中随处可见&#xff0c;比…

怎样自己写一个MVC框架

最近想学习php的mvc结构&#xff0c;在网上找了一些资料&#xff0c;可是大部分都是相同的&#xff0c;或者写的不是很满意。接着看了一个cakephp的框架&#xff0c;感觉太多的函数了&#xff0c;让人觉得就是一个记函数的过程&#xff0c;所以觉得不是很好。 我对mvc的理解是&…

NET问答: LINQ 中为啥不能将 StartsWith() 转成 Like('abc%') ?

咨询区 Techy&#xff1a;我有下面的一段 asp.net core LINQ 代码。List<UserSearchResult> results await db.ApplicationUsers.Where(u > u.Name.StartsWith(name) && !u.Deleted && u.AppearInSearch).OrderByDescending(u > u.Verified).Then…

python for net_转:.NET 4.0 下使用 Python for .NET

转&#xff1a;首先&#xff0c;我要搞清楚Python for .NET ,IronPython 它们之间的区别。Python 作为一门语言&#xff0c;其解释器(因为是解释型动态语言&#xff0c;所以我觉得称之为解释器 interpreter 比编译器 compiler 更合适)并不是只有唯一实现的。通常我们从 Python…

Python应用02 Python服务器进化

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; **注意&#xff0c;在Python 3.x中&#xff0c;BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer整合到http.server包&#xff0c;SocketServer…

天赋差的程序员,难道就只能半途而废吗?

全世界只有3.14 % 的人关注了数据与算法之美在很多人看来&#xff0c;也许优秀的程序员靠的就是与生俱来的强大天赋&#xff0c;外加蜻蜓点水般的时间付出&#xff0c;就能够炼就算无遗漏的编码技能。那么果真是如此吗&#xff1f;身为不太聪明的开发者难道就活该中途止步吗&am…

html让ul的li自动居中,css ul li导航菜单居中问题解决方法

昨晚群里一个朋友帮忙解决的问题&#xff0c;之前没有遇到过&#xff0c;题目如下&#xff1a;不改变html结构&#xff0c;使导航菜单垂直水平居中&#xff0c;导航宽度自适应屏幕100%&#xff0c;高度30px;单项高度28px,宽80px;兼容&#xff1a;ie6,ff,chrome,opera等主流浏览…

String是一个奇怪的引用类型

点击蓝字关注我们开局两张图&#xff0c;内容全靠刷。马甲哥看到这样的现象&#xff0c;一开始还是有点懵逼。这个例子&#xff0c;string是纯粹的引用类型&#xff0c;但是在函数传值时类似于值传递&#xff1b;我之前给前后示例的内存变化图吧&#xff1a;根因就是大多数高级…

js 浅拷贝直接赋值_浅析JavaScript解析赋值、浅拷贝和深拷贝的区别

一、赋值(Copy)赋值是将某一数值或对象赋给某个变量的过程&#xff0c;分为&#xff1a;1、基本数据类型&#xff1a;赋值&#xff0c;赋值之后两个变量互不影响2、引用数据类型&#xff1a;赋**址**&#xff0c;两个变量具有相同的引用&#xff0c;指向同一个对象&#xff0c;…

限时秒杀│中科院推荐!6个引自美国NASA盒子,玩转科学

比勤奋更重要的&#xff0c;是孩子的思维能力。从上幼儿园开始&#xff0c;很多父母很喜欢给孩子报各种兴趣班&#xff0c;比如钢琴班、英语班、乐高班、报各种各样的课程&#xff0c;就是希望孩子具有18般武艺&#xff0c;赢在起跑线上。其实除了外在的能力&#xff0c;不显山…

html语言可以写模版继承吗,Django框架(十一):模板介绍、模板语言、模板继承、HTML转义...

1. 模板介绍1.1 模板的功能产生html&#xff0c;控制页面上展示的内容。模板文件不仅仅是一个html文件。模板文件包含两部分内容&#xff1a;静态内容&#xff1a;css、js、html。动态内容&#xff1a;用于动态去产生一些页面内容。通过模板语言来产生。1.2 模板文件的使用通常…

sed-笔记

一&#xff0e;sed脚本编程的方法论 1. 在着手做之前要弄清楚想做什么。2. 明确地描述处理的过程。3. 在提交最终的改变之前反复测试这个过程。注1&#xff1a;检测脚本最好的方式&#xff0c;是使用不同的输入样本进行测试并观察结果。二&#xff0e;…

.NET6又出新版本,新增这几个大杀器!

.NET6 Preview4终于发布了&#xff0c;作为第4个预览版&#xff0c;伴随着Build2021发布的&#xff0c;器更新内容也是非常丰富的。推荐关注的有以下11项&#xff1a;引入最小 API异步流HTTP 日志中间件新项目中使用 Kestrel 作为默认启动IConnectionSocketFeature改进单页应用…

蜗杆参数法设计_技术贴 | 减速器结构及设计的注意事项

减速机器用于低转速大扭矩的传动设备&#xff0c;原理是把电动机、内燃机、马达或其它高速运转的动力&#xff0c;通过减速机的输入轴上齿数少的齿轮啮合输出轴上的大齿轮&#xff0c;从而达到减速的目的&#xff1b;大小齿轮的齿数之比&#xff0c;就是传动比。减速器是一种由…

听说热爱生活的人都关注了他们

全世界有3.14 % 的人已经关注了数据与算法之美在信息爆炸的时代快节奏的生活里 你是否曾有一瞬间觉得忙碌而空虚&#xff1f;以下10个优质公众号能让你在闲暇的时候不断的提升自我&#xff0c;拓宽视野愿以书卷气&#xff0c;行我路千里近现代史研究通讯ID&#xff1a;jxsdyjtx…

基于abp vnext制作项目脚手架

首先说明&#xff0c;尊重原创&#xff0c;本文是参考https://www.cnblogs.com/myshowtime/p/14507675.html这篇文章写的&#xff0c;里面内容有部分是直接拷贝过来的。感谢作者分享&#xff01;&#xff01;&#xff01;前期准备工作使用命令 abp new LS.Template --template …

Windows Server 2012 DHCP 服务器中的新功能:故障转移和策略

Windows Server 2012 DHCP 服务器中的新功能如下&#xff1a; DHCP 故障转移&#xff1a;此功能提供让两个 DHCP 服务器服务于 同一子网或作用域的 IP 地址和选项配置的能力&#xff0c;前提是 DHCP 服务对客户端持续可用。两个 DHCP 服务器复制它们之间的租用信息&#xff0c;…

android mvc mvp 简书,浅析 MVP,MVC,MVVM模式(Android)

前言当我们接手一个项目的时候&#xff0c;经常会发现一个activity或fragment动辄上千行甚至上万行代码&#xff0c;这给阅读带来很大的困扰&#xff0c;如果想读懂代码&#xff0c;需要花费很多时间跟精力。引起这个问题的原因想必大家都了解&#xff0c;随着人员不断变动&…