11-有符号数和无符号数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35733751/article/details/85072540

1. 有符号数和无符号数

无符号数,因为没有符号位,所以只能表示一个正数。

有符号数,因为存在符号位,符号位如果是0的话,代表这是一个正数,符号位如果是1的话,代表这个数是一个负数。

 

我们可以用db伪指令来声明一些数字:

 

编译之后:

10D的十六进制表示就是0x0A,11D的十六进制表示就是0x0B,17D的十六进制表示就是0x11

 

但自从学习汇编语言,我们还没有用过负数,好像汇编语言里面根本就没有负数一样。为此,现在有一个十进制的负数-3d,要求转换成1个字节,并用十六进制来表示。

 

修改db伪指令:

db 10,11,17,-3

 

编译后的结果:

我们可以看到-3的十六进制数竟然是FD,那么这个FD到底是怎么来的呢?

首先十进制3的二进制是:0000 0011,因为十进制-3是负数,所以符号位是1,推导出-3的原码:1000 0011,我们需要根据原码转换成计算机表示的补码(关于反码,补码的计算规则相信大家应该还记得吧):

-3的反码就是:1111 1100

-3的补码就是:1111 1101

转换成十六进制就是:FD

 

那么问题来了,253D的十六进制表示也是FD,这意味着无论是253还是-3,汇编器统统都给转换成FD了,也就是说,FD既可以代表-3又可以代表253,那假如给你一个FD,那么你认为它代表什么呢?

看到上面这张图是不是很懵逼??? 其实这个问题放在几十年前,那时的计算机工程师面对这种情况同样也很懵逼。

对于1111 1101这个数,你既可以理解为-3,也可以理解为253。也就是说,在计算机里几乎所有的指令,既能操作无符号数,又能操作有符号数,并且结果完全都正确,怎么理解由你自己决定。

但总有例外,比如除法指令和乘法指令,div指令就只能完成无符号除法指令(Unsigned Divide),如果是完成有符号除法指令(Signed divide),就要使用idiv指令。这两个指令的使用方法是一样的,区别在于div是针对无符号数,而idiv是针对有符号数。

C语言同理,我们来看下面这段代码:

int main(void)
{
	//对于数字12在C语言中,也有无符号,有符号数两种表示方法
	int num1 = 12;				//一般默认是有符号数,signed
	unsigned int num2 = 12;		//使用unsigned关键字明确指定为无符号数
	return 0;
}

因此,在汇编语言中计算数字时,这个数字是有符号数还是无符号数由你自己决定,在C语言中也是同样的道理。

 

2. 标志寄存器

这一节我们要学习一个新的寄存器,叫做标志寄存器。关于标志寄存器,在16位的汇编语言中,这个寄存器叫做flag。在32位的汇编语言中,这个寄存器叫做eflag,即标志寄存器EFL。

标志寄存器EFL在计算机的作用是主要反映处理器的状态和ALU运算结果的某些特征

比如CF这个标志位,翻译过来指的是(CarryFlag),当进行无符号运算的时候,如果产生进位和借位,CF就会变成1,否则变成0。

 

来看一个示例:

;al是一个8位的寄存器,最大只能存放1111 1111(0xFF),在这种情况下,如果再加1的话,就会产生溢出。
mov al,0xFE
inc al	
inc al	

执行第二条add指令时,寄存器ax里的内容就会溢出,而标志寄存器里的CF标志位就会置为1。

 

当把add指令换成inc指令,我们发现寄存器ax的内容溢出时,CF标志位并没有置1,至于原因,书上的解释是inc指令不会影响CF标志位。

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/85072540