转载自:http://hi.baidu.com/asmsky/blog/item/7290d20076cab6da277fb5b8.html

一、只有一个标准!

在汇编语言层面,声明变量的时候,没有 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就不存在这个问题,因为它被设计成所有的整数都是有符号的)。为了说明c的可怕特举一例:

#include #include 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 的。(完)

附录

1:IA-32 Intel Architecture Software Developer’s Manual》第2卷PDF文档表述为“sign-extended imm8”,这个sign-extended 是符号扩展的意思。说说符号扩展:当操作数进行长度扩展时,既要让操作数变长又不能改变原数值,所以就出现了符号扩展一说。比如 movsx ax, 0xEC   ,执行扩展后,ax的值为:0xFFEC,长度变长了,结果没变,都是 -20 。

2:两套乘法指令结果例程

;; 程序存储为 x.s

;;--start--------------------------------------------------------

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

阅读(5657) | 评论(0) | 转发(1) |

linux有符号和无符号,汇编中有符号与无符号数的区分相关推荐

  1. 汇编中有符号与无符号数以及CF,OF标志位的区分

    汇编中有符号与无符号数以及CF,OF标志位的区分 一. 只有一个标准! 首先需要知道,计算机对数值的存储采用补码形式存储,一来避免了+0和-0的尴尬,二来数值的加法和减法可以统一为补码的加法. 在汇编 ...

  2. 关于汇编中有符号数和无符号数的判断

    首先给一段代码 1 #include <stdio.h> 2 int main() 3 {unsigned int x=9; 4  int y=-20; 5  int m=(x+y> ...

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

    1.原码.反码.补码知识的复习: 三者的最高位均为符号位.我以前一直没弄明白的是为何8位补码的表示范围是-128~127,今天查阅了相关资料,于此记下. 仍然以8位为例: 原码的表示范围:-127~- ...

  4. 对verilog中有符号数和无符号数的理解

    文章目录 对verilog中有符号数和无符号数的理解 对verilog中有符号数和无符号数的理解 ​ verilog中使用signed表示有符号数,比如: wire signed [7:0] din; ...

  5. C语言中的有符号与无符号(挖坑)

    1.计算机中的符号位,计算机如何表示正数和负数? 数据类型的最高位用于标识数据的符号 最高位为1,表明这个数为负数 最高位为0,表明这个数为正数 2.有符号数的表示法 在计算机内部用补码表示有符号数 ...

  6. 整型和短整型,有符号和无符号

    整型变量分类 短整型:short int 整型:int 长整型:long int 无符号短整型:unsigned short 无符号整型:unsigned int 无符号长整型:unsigned lo ...

  7. c语言 有符号数与0作比较大小,C语言中有符号数与无符号数能否进行比较运算...

    无符号数和有符号数是不能进行比较运算的,否则可能会出现意想不到的错误,且极难检查出来! 首先肯几个例子(假设在32位的机器上): 1         1. 0 == 0U 2         2. - ...

  8. FPGA设计中 有符号数、无符号数

    FPGA设计中 有符号数.无符号数 今天给大侠聊一聊FPGA设计中有符号数以及无符号数,话不多说,上货. 在设计中,所有的算数运算符都是按照无符号数进行的.如果要完成有符号数计算,对于加.减操作通过补 ...

  9. 有符号数和无符号数的转换及思考

    1 有符号数和无符号数的表示 三者的最高位均为符号位. 我以前一直没弄明白的是为何8位补码的表示范围是-128~127, 今天查阅了相关资料,于此记下. 仍然以8位为例: 原码 原码的表示范围-127 ...

最新文章

  1. python pillow 图片处理
  2. thinkphp 视图模型 两个字段映射同一个表
  3. 2020年六月份qq邮箱代收搜狐邮箱
  4. SAP CAP 编程模型简介
  5. 出国?上研?工作?回家种田?(一) 出国看世界
  6. 方正计算机软件保护进超级用户,超级用户权限补丁(SuperSU Pro)含刷机包
  7. elasticsearch实现远程索引复制
  8. mysql循环遍历获取_MySQL 全表遍历
  9. linux中脚本后台执行的方法
  10. C#开源大全--汇总
  11. 打印机出现另存为xps_win7系统打印文件时弹出另存为xps/pdf的解决方法
  12. 如何注册海外邮箱?如何进行邮箱注册163,这些技巧交给你
  13. 解决Only fullscreen activities can request orientation的方法
  14. 深圳电视台小间距P2高清圆弧屏(弧形屏)是用软模组(软屏)拼成
  15. Python Curses
  16. MOS管驱动电路设计,如何让MOS管快速开启和关闭?
  17. NLTK基础基础教程学习笔记(十四)
  18. Tomcat启动报错org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to sta
  19. rm -rf命令的作用 以及windows 代替命令
  20. vijos P1443 银河英雄传说

热门文章

  1. mac M1 brew services报错
  2. 安卓应用提供64位原生的支持
  3. 西瓜书课后题8.5(bagging)
  4. Nginx安装以及详解
  5. 修改PLSQL中文乱码问题
  6. 解决plsql解决中文乱码问题
  7. 学习Machine Leaning In Action(二):kNN
  8. Java中OOA、OOD、OOP、OOT、OOSM、OOM的具体含义解释
  9. 利用auto.js实现fifaol3刷助教
  10. wordcloud参数