有符号数,无符号数,补码,溢出_of判断-程序员宅基地

技术标签: C/C++  

1、加减运算指令是不区分有符号和无符号的,编程人员自己要心理有数。

说清这个问题,需要理解几个概念:
1. CF 进位标志位 Carry Flag
反映运算是否产生进位或者借位的操作,如果运算结果的最高位产生了一个进位或错位,那么,其值为1,否则为0。

2. OF 溢出标志 Overflow Flag
溢出标志OF用于反映有符号数 加减运算所得结果是否溢出,如果运算结果超过当前运算位数所能表示的范围,则成为溢出,OF的值被设置为1,否则OF的值被清为0。 溢出和进位是两个不同的概念 。

3.在PC系统中,有符号数用补码表示. 正数的补码是其本身,负数的补码是其对应正数取反加一,
补码表示,使得加减法统一了起来。

4. pc 中正负数是靠最高为来判断的,最高为就等于SF, (sf=0 为正, sf=1为负)

5. 给定一个数,如果你认为它是正数,要用CF 判断溢出。 判断大小也用CF
    如果你认为它是负数,要用OF 判断溢出。 判断大小也用要用OF,SF配合使用。 具体怎么配合这就不说了

CPU只会根据输入信号进行逻辑运算,在硬件级别是没有有符号无符号的概念,运算结束会根据运算前的信号和输出信号来设置一些标志位,是不是有符号由写程 序的人决定,标志位要看你把操作数当有符号还是无符号来选择,就像内存中的数据,你可以按照需要来解析,原始数据在那里,你要按什么数据格式来解析在于自 己的选择,所以 玩汇编的要做到心里有数

继续
关于有符号数和无符号数,LZ看看这个吧:




 有符号数和无符号数探讨  
  

 
这个问题,要是简单的理解,是很容易的,不过要是考虑的深了,还真有些东西呢。
下面我就把这个东西尽量的扩展一点,深入一点和大家说说。
 
一、只有一个标准!
 
在 汇编语言层面,声明变量的时候,没有 signed 和 unsignde 之分,汇编器统统,将你输入的整数字面量当作有符号数处理成补码存入到计算机中,只有这一个标准!汇编器不会区分有符号还是无符号然后用两个标准来处理, 它统统当作有符号的!并且统统汇编成补码!也就是说,db -20 汇编后为:EC ,而 db 236 汇编后也为 EC 。这里有一个小问题,思考深入的朋友会发现,db 是分配一个字节,那么一个字节能表示的有符号整数范围是:-128 ~ +127 ,那么 db 236 超过了这一范围,怎么可以?是的,+236 的补码的确超出了一个字节的表示范围,那么拿两个字节(当然更多的字节更好了)是可以装下的,应为:00 EC,也就是说 +236的补码应该是00 EC,一个字节装不下,但是,别忘了“截断”这个概念,就是说最后汇编的结果被截断了,00 EC 是两个字节,被截断成 EC ,所以,这是个“美丽的错误”,为什么这么说?因为,当你把 236 当作无符号数时,它汇编后的结果正好也是 EC ,这下皆大欢喜了,虽然汇编器只用一个标准来处理,但是借用了“截断”这个美丽的错误后,得到的结果是符合两个标准的!也就是说,给你一个字节,你想输入 有符号的数,比如 -20 那么汇编后的结果是符合有符号数的;如果你输入 236 那么你肯定当作无符号数来处理了(因为236不在一个字节能表示的有符号数的范围内啊),得到的结果是符合无符号数的。于是给大家一个错觉:汇编器有两套 标准,会区分有符号和无符号,然后分别汇编。其实,你们被骗了。:-)
 
二、存在两套指令!
 
第一点说明汇编器只用 一个方法把整数字面量汇编成真正的机器数。但并不是说计算机不区分有符号数和无符号数,相反,计算机对有符号和无符号数区分的十分清晰,因为计算机进行某 些同样功能的处理时有两套指令作为后备,这就是分别为有符号和无符号数准备的。但是,这里要强调一点,一个数到底是有符号数还是无符号数,计算机并不知 道,这是由你来决定的,当你认为你要处理的数是有符号的,那么你就用那一套处理有符号数的指令,当你认为你要处理的数是无符号的,那就用处理无符号数的那 一套指令。加减法只有一套指令,因为这一套指令同时适用于有符号和无符号。下面这些指令:mul div movzx … 是处理无符号数的,而这些:imul idiv movsx … 是处理有符号的。
举例来说:
内存里有 一个字节x 为:0x EC ,一个字节 y 为:0x 02 。当把x,y当作有符号数来看时,x = -20 ,y = +2 。当作无符号数看时,x = 236 ,y = 2 。下面进行加运算,用 add 指令,得到的结果为:0x EE ,那么这个 0x EE 当作有符号数就是:-18 ,无符号数就是 238 。所以,add 一个指令可以适用有符号和无符号两种情况。(呵呵,其实为什么要补码啊,就是为了这个呗,:-))
乘法运算就不行了,必须用两套指令,有符号的情况下用imul 得到的结果是:0x FF D8 就是 -40 。无符号的情况下用 mul ,得到:0x 01 D8 就是 472 。(参看文后附录2例程)
 
三、可爱又可怕的c语言。
 
为 什么又扯到 c 了?因为大多数遇到有符号还是无符号问题的朋友,都是c里面的 signed 和 unsigned 声明引起的,那为什么开头是从汇编讲起呢?因为我们现在用的c编译器,无论gcc 也好,vc6 的cl 也好,都是将c语言代码编译成汇编语言代码,然后再用汇编器汇编成机器码的。搞清楚了汇编,就相当于从根本上明白了c,而且,用机器的思维去考虑问题,必 须用汇编。(我一般遇到什么奇怪的c语言的问题都是把它编译成汇编来看。)
 
C 是可爱的,因为c符合kiss 原则,对机器的抽象程度刚刚好,让我们即提高了思维层面(比汇编的机器层面人性化多了),又不至于离机器太远(像c# ,java之类就太远了)。当初K&R 版的c就是高级一点的汇编……:-)
 
C又是可怕的,因为它把机器层面的所有的东西都反应了出来,像这个有没有符号的问题就是一例(java就不存在这个问题,因为它被设计成所有的整数都是有符号的)。为了说明它的可怕特举一例:
 
#include <stdio.h> 
#include <string.h> 
 
int main()
{
    int x = 2; 
    char * str = "abcd"; 
    int y = (x - strlen(str) ) / 2;
     
    printf("%d\n",y);
}
 
结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值,类型是size_t,也就是unsigned int ,与 int 混合计算时有符号类型被自动转换成了无符号类型,结果自然出乎意料。。。
观察编译后的代码,除法指令为 div ,意味无符号除法。
解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成 idiv 了。
我 们知道,就是同样状态的两个内存单位,用有符号处理指令 imul ,idiv 等得到的结果,与用 无符号处理指令mul,div等得到的结果,是截然不同的!所以牵扯到有符号无符号计算的问题,特别是存在讨厌的自动转换时,要倍加小心!(这里自动转换 时,无论gcc还是cl都不提示!!!)
 
为了避免这些错误,建议,凡是在运算的时候,确保你的变量都是 signed 的。
 
四、c的做法。
 
对 于有符号和无符号的处理上,c语言层面做的更“人性化”一些。比如在声明变量的时候,c 有signed 和 unsigned 前缀来区别,而汇编呢,没有任何区别,把握全在你自己,比如:你想在一个字节中输入一个有符号数,那么这个数就别超过 -128 ~ +127 ,想输入无符号数,要保证数值在 0~255 之间。如果你输入了 236 ,你还要说你输入的是有符号数,那么你肯定错了,因为有符号数236至少要两个字节来存放(为00 EC),不要小看了那一个字节的00,在有符号乘法下,两个字节的00 EC 与 一个字节的EC,在与同样一个数相乘时,得到的结果是截然不同的!!!
 
我们来看下具体的列子(用vc6的cl编译器生成):
 
C语言 编译后生产的汇编语言 
    ……
    char x;
    unsigned char y;
    int z;
     
    x = 3;
    y = 236;
 
    z = x*y;
    …… ……
    _x$ = -4
    _y$ = -8
    _z$ = -12
    …… 
    mov BYTE PTR _x$[ebp], 3
    mov BYTE PTR _y$[ebp], 236  
 
    movsx eax, BYTE PTR _x$[ebp]
    mov ecx, DWORD PTR _y$[ebp]
    and ecx, 255 
     
    imul eax, ecx
    mov DWORD PTR _z$[ebp], eax
    …… 


 
我 们看到,在赋值的时候(绿色部分),汇编后与本文第一条论述相同,是否有符号把握全在自己,c比汇编做的更好这一点没有得到体现,这也可以理解,因为c最 终要被编译成汇编,汇编没有在变量声明时区分有无符号这一功能,自然,c也没有办法。但既然c提供了signed和unsigned声明,汇编后,肯定有 代码体现这一点,表格里的红色部分就是。对有符号数x他进行了符号扩展,对无符号y进行了零扩展。这里为了举例的方便,进行了有符号数和无符号数的混合运 算,实际编程中要避免这种情况。
 
(完)
 
 
附录:
 
1.计算机对有符号整数的表示只 采取一套编码方式,不存在正数用原码,负数用补码这用两套编码之说,大多数计算机内部的有符号整数都是用补码,就是说无论正负,这个计算机内部只用补码来 编码!!!只不过正数和0的补码跟他原码在形式上相同,负数的补码在形式上与其绝对值的原码取反加一相同。
 
2. 两套乘法指令结果例程:
 
;; 程序存储为 x.s
 
extern printf 
global main 
 
section .data
    str1: db "%x",0x0d,0x0a,0 
    n: db 0x02
section .text 
main: 
    xor eax,eax
    mov al, 0xec
    mul byte [n] ;有符号乘法指令为: imul
 
    push eax
    push str1
    call printf 
     
    add esp,byte 4 
    ret 
     
编译步骤:
1. nasm -felf x.s 
2. gcc x.o
 
ubuntu7.04 下用nasm和gcc编译通过。结果符合文章所述。

Sandisk
二、有符号数运算时的溢出
      如果计算机的字长为n位,n位二进制数的最高位为符号位。其余n-1位为数值位,采用补码表示法时,可表示的数X的范围是
                       有符号数,无符号数,补码,溢出
       当n=8时,可表示的有符号数的范围为-128~+127;当n=16时,可表示的有符号数的范围为 -32768~+32767。两个有符号数进行加减运算时,如果运算结果超过可表示的有符号数的范围时,就会发生溢出,使计算机结果出错。很显然,溢出只 能出现在两个同号数相加或两个异号数相减的情况。具体的讲,对于加运算,如果次高位(数值部分最高位)形成进位加入最高位,而最高位(符号位)相加(包括 次高位的进位)却没有进位输出时;或者反过来,次高位没有进位加入最高位,但最高位却有进位输出时,都将发生溢出。因为这 两种情况分别是:两正数相加,结 果超出了范围,形式上变成了负数;两负数相加,结果超出了范围,形式上变成了正数 。
            例 (+72)+(+98)             例   (-83)+(-80)
    对 于减运算,当次高位不需从最高位借位,但最高位却需借位(整数减负数,差超 出范围);或者反过来,次高位需从最高位借位,但最高位不需借位(负数减整数,差 超出范围),也会出现溢出
            例   (+72)-(-98)               例   (-83)-(+80)
    综合以上是否溢出的判断:最高位的进位位 有符号数,无符号数,补码,溢出 次高位的进位位=1,则OF被置1。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/a627088424/article/details/9173831

智能推荐

解决GNU Radio+USRP实现OFDM收发在接收端QPSK星座图映射无“抖动”问题_基于gnuradio与usrp的qpsk-程序员宅基地

文章浏览阅读837次,点赞8次,收藏9次。本文记录在 GNU Radio+USRP 实现 OFDM 收发时,在接收端 QPSK 星座图映射无“抖动”问题的解决方法,_基于gnuradio与usrp的qpsk

php 省级联动,php实现省级联动-程序员宅基地

文章浏览阅读115次。县各级已建、在建、要建电子政务系统成果为基础,构建我省国土资源省-市-县三级联动政务管理系统框架,在全省行政管理的推动力下,实现全省国土资源全业务、全流程的......的适度 第二、统建三级协同框架,分建各级业务系统 第三、统一制定标准规范,分级开展系统集成 三、省-市-县三级联动政务系统框架 省级 省厅用户省厅用户 省级 …......1 研究方法与数据 使用铁路客运车次数据刻画我国中心城市之间..._php 行政区域json 5级联动

J-Link RTT Viewer连接后不能打印问题-程序员宅基地

文章浏览阅读628次,点赞12次,收藏10次。因为RTT Control Block比较靠后,所以自动探测并没有找到,我们选择Address,然后手动输入RTT Control Block地址即可。首先找到编译出来的.map文件,打开文件后搜索“_acUpBuffer”,找到这个变量后,这个变量上面是“.bss”,复制这一行的地址。RTT Control Block 选择 Auto Detection,没有任何打印输出。1、J-Link RTT Viewer不能打印问题。按下图填入再连接,打印正常。_j-link rtt viewer

如何申请Office 365 E5开发者账号,开通OneDrive 5T空间教程_onedrive e5账号-程序员宅基地

文章浏览阅读1w次,点赞2次,收藏22次。个人免费版OneDrive只有5G空间,而Office 365 E5账号的OneDrive有5T存储空间,且可以开通25个每个5T空间的子号,并可激活Office 365使用。不过,Office 365 E5只有90天的试用期,如果到时候无法续期,则OneDrive也会被停止使用。申请及使用方法:1、浏览器打开网址:https://developer.microsoft.com/zh-cn/office/dev-program,新注册账号或用已有的微软账号登录,手机接收验证码即可完成注册。2、.._onedrive e5账号

UE4 动画重定向_重定向管理窗口ue4-程序员宅基地

文章浏览阅读627次。1.首先导入你要重定向的人物_重定向管理窗口ue4

heatmap(热图)_热图和热力图一样吗-程序员宅基地

文章浏览阅读6.1k次。热图有时候叫热区图或者热力图,都是用于表现某种事物密集度的图形化显示。我写的这个没有画底图,不然会更好趣,比如一个键盘,一张房屋平面图,或者一张Google地图,拿它做什么用,完全取决于你的需要。二、原理1、首先可以参考下面几个链接[heatmap.js 一个用canvas画热力图的利器] http://www.cnblogs.com/bdqlaccp/archive/2012/09/12..._热图和热力图一样吗

随便推点

又双叒获奖了!中国铁建再添桥梁届“诺贝尔奖”两项!-程序员宅基地

文章浏览阅读139次,点赞8次,收藏3次。在原有桥两侧,各建造一座桥宽约3.5米的竹拱桥,该竹拱桥贯彻“低碳、绿色、节能、环保”的建造理念,充分利用当地竹材的产业优势,实现了构件标准化制作和全预制快速拼装,不仅施工周期短,而且对周边环境的影响很小,为当地打造一座特色景区“绿色桥梁”,推动了竹拱桥的技术进步。同时,当地可依托竹建筑,依据自然环境与功能,找准自身定位,结合地域文化特色,整合文化旅游、乡村振兴建设等相关资源,打造文化振兴可持续发展之路,也为未来景区、乡村等多领域特色桥梁建设提供参照标准,更对以后竹加工产业链不断延长与深入有着里程碑意义。

CatiaV5R21安装_catia v5r21安装后打不开-程序员宅基地

文章浏览阅读5.3k次,点赞2次,收藏8次。catia二次开发环境搭建方案catia V5R21(32位安装)方案windows10系统,VS2008,catia V5R21(32位)catia V5R21(32位安装)注意:windows10系统如果安64位的catia V5R21,破解后,会闪退,打不开。所以只能安装32位。安装文件和教程:https://www.32r.com/soft/16315.html安装后第一次打开:..._catia v5r21安装后打不开

基于openssl库实现AES加密(C语言)_aes_set_encrypt_key-程序员宅基地

文章浏览阅读6.1k次。一、AES加密算法 _aes_set_encrypt_key

C3P0 jar包 含源码 下载_c3p0 0.9.1.2.jar下载-程序员宅基地

文章浏览阅读3.5k次,点赞11次,收藏3次。百度云链接:https://pan.baidu.com/s/15jsDhTXgaYRIO51fHFGwyA提取码:b1l1复制这段内容后打开百度网盘手机App,操作更方便哦蓝奏云下载地址源码位置:1.解压c3p0-0.9.1.2.src.zip2.打开c3p0-0.9.1.2.src下面的src,导入方式为文件夹..._c3p0 0.9.1.2.jar下载

SDN控制器Floodlight--容错部署(FT)_windiws运行floodlight-程序员宅基地

文章浏览阅读1.1k次。很久没写了,最近太忙没来及学习了。最近看了下Floodlight的容错部署方式,在官网上有专门的介绍: (https://floodlight.atlassian.net/wiki/spaces/floodlightcontroller/pages/36143107/How+to+Add+Fault+Tolerance+to+the+Control+Plane) 但是我在实际操作过程中还是遇到些_windiws运行floodlight

记录大厂的一些面试题(后续更新)-程序员宅基地

文章浏览阅读294次。前言记录最近一段时间面试大厂的一些面试题,用作保留并分享腾讯篇移动端自适应布局答:rem适配,动态计算html的fontsizecss动画和js动画的区别答: CSS动画:①代码相对简单,性能调优方向固定,②对于帧速表现不好的低版本浏览器,CSS3可以做到自然降级,而JS则需要撰写额外代码css绝对居中答:css居中各种奇淫技巧css块元素和行内元素答:c..._关于gcd大厂面试

推荐文章

热门文章

相关标签