这是计算机组成原理的问题。计算机怎样表明负数。最高位为0,表明正数,最高位为1表明负数,例如
0b 0000 0011 表明 +3
0b 1111 1111 表明 -1
所以,那么数值的取值规模便是这么来的,一个字节有8位,假如是无符号数,那么就能表明 0~255 总共 256个数,可是假如是有符号数,也便是说这8位里边还需求表明一个符号,并且负号在最高位,那么数值只能是 bit0 ~ bit 7 表明,也便是说 -128 ~ 127
计算机里边做的运算都是补码运算,有符号数仍是无符号数,计算机是不论的,其实这个仅仅写给编译器看的,由编译器去辨认。并且生成相对应的代码。
原码,反码,补码的改换
原码,原本的数据叫原码,反码是各位取反,补码有详细的运算规矩。
例如signed char 类型的数据 +3
原码 0b 0000 0011 最高位为0,表明正数。
反码 0b 1111 1100 很简单,各位取反。
补码运算规矩
1, 假如是正数,那么补码=原码
2, 假如是负数,那么补码=原码的反码+1
上面比如,+3的补码为 0b 0000 0011 ,和原码相同。
假如换成 -3 那么状况便是
0000 0011 à 1111 1100 + 1 à 1111 1101 这个便是 -3 的补码,计算机便是这样表明负数的。
所以今日研讨了一下EMC单片机的加减运算
由所以用汇编写的,那么就压根没有所谓的有符号数和无符号数的差异。所以程序里边能够以为的确定,也便是我,我以为是他有符号,仍是无符号。最费事的便是越界问题,数据过大溢出了。可是只需求记住一点,单片机电路是依照补码运算的,含糊的回忆中想起了当年数字电路课程里边呈现的东西,不过回忆现已很含糊了。得温习一下。
最重要的是:计算机里边都是依照补码来运算的!!这是由数字逻辑电路决议的。
怎样和 C 进位联合起来。所以我想从几种状况剖析。
1, 加法的状况,2+3 = 5 ,只需是智力没有问题的都不会算错吧 ……
单片机里边的状况,咱们以为这个是有符号数,那么便是2个正数相加,
这儿要注意的,“我当他是有符号数”是我人为加以假定,单片机可不吃这一套,横竖,只需履行 mov 指令将数据送到单片机,那么单片机就以为这是补码,他可不论你有没有符号。
那么进程是这样:
大脑里边人为这两个是补码,那么依据补码的运算规矩,正数的补码便是原码,得到
0000 0010
+ 0000 0011
————————–
0000 0101
进位 C=0 表明加法没有溢出。
这便是单片机的运算成果了。
单片机便是得到这个东西,这个是一个补码,由于单片机只知道补码,其他他不知道。那么然后咱们将做小处理。
假如咱们大脑将他当作是无符号数,那么这儿表明的是 5 ,假如咱们将他当作有符号数,那么这儿表明的便是 +5 (由于最高位为0,原码和补码相同)
2, 假如两个数据比较大,相加会溢出,这怎样处理。0xff+0xff = ?
1111 1111
+ 1111 1111
————————–
1 1111 1110
进位 C=1 表明加法运算有进位。
那么其实这儿表明的是 FF + FF =1FE ,C代表最高位,跟一般加法运算是相同的,由于计算机当成补码,他不论你什么数,他就依照补码运算。
3, 减法运算,差是正数: 3-2 = 1
前面加法,补码基本上没啥进场时机,可是减法就不同,减法便是补码发挥作用的时分。记曾经数字电路的教师说过,数字电路只要加法器(全加器和半加器),是没有减法器的,所以计算机对待减法运算,实际上是用加法运算替代的。那么
3-2 能够转化为 3+(-2) 这个便是加法运算了。然后考虑两个数的补码。3为正数,所以补码为原码自身,-2 为负数,补码为反码后再加1,那么加过是
3 :0011
-2 :1110
那么 3-2 单片机运算的成果,实际上相当于 0011 + 1110 的成果,是
0000 0011
+ 1111 1110
————————–
1 0000 0001
C=1表明减法没有借位,成果为 00000001,这是一个补码,因而这个是正数,所以原码是他自身,也便是说成果为 1 ,没有错位,也便是说 被减数大于减数。
EMC单片机的代码是:
mov a,@3
mov 0x20,a
mov a,@2
sub 0x20,a
0x20寄存终究成果,仿真运转成果,0x20数值为 1,C=1表明没有借位,Z=0表明运算成果非零。这个跟咱们剖析的彻底符合。
咱们推行一下:
已然咱们说了 3-2 终究会被计算机转化为补码加法,那么我将上面的EMC单片机的代码手艺做成加法,那么等待得到的成果应该是相同的。
mov a,@3
mov 0x20,a
mov a,@0xfe
add 0x20,a
仿真运转成果,0x20数值为 1,C=1表明加法运算进位了,Z=0表明运算成果非零。这个跟上面的减法运算成果是一模相同的。这便是咱们等待的成果,证明了单片机里边是补码的运算。
4, 减法运算,差是负数,也便是说不行减,例如 2-3 = -1
这个运算在单片机里边究竟是怎样进行的呢?其实也很简单,记住咱们的信条:“单片机里边都是补码运算”那么很天然的化成 2 + (-3),求出 2 和 -3的补码并进行运算
0000 0010
+ 1111 1101
————————–
0 1111 1111
进位位C = 0表明减法运算产生错位,成果是 0b11111111,这便是终究成果了。
可是这个值咱们要看的懂,有必要改变为原码,说过了,这是一个补码,最高位为1表明这是一个负数,所以求原码的方法,也是将补码取反再加一,也便是
0b11111111 à 0b00000000+1 à 0b00000001
这个便是咱们终究的成果,是一个负数,绝对值为1,也便是说成果为 -1
这跟咱们等待的成果是一模相同的。EMC单片机仿真代码以及成果:
mov a,@2
mov 0x20,a
mov a,@3
sub 0x20,a
寄存器0x20的值为 0xff,进位C=0表明减法产生了错位,Z=0表明成果非零。
这彻底和咱们剖析的符合。再着重,单片机里边呈现的都是补码,所以这成果的 0xff 也是补码,想看懂得转化为原码。上面现已说了转化方法。
别的,咱们需求分隔来看,咱们上面是说将这个数字当作是“有符号数”,2-3=-1这个是咱们要的成果,可是,假如咱们把这个数当作是“无符号数”那又该怎样办呢?
方法便是,借位,跟咱们手艺减法相同,不行减就向高位借位。
2-3 = 0010 – 0011 这是不行减的,那么 2应该向高位借一,变成 10010 – 0011 = 1111,这儿扮演高位的其实便是进位C,也便是说C=0时是产生错位的,为什么?由于这个C=1被被减数借去用了,成果为 0xff ,这个时分 0xff 便是咱们想要的成果,不需求改变,由于咱们不是当作有符号数。
5, 两个数比较巨细 CMP A , B
两个数比较巨细,记住曾经微机原理的教师给咱们说了,实质便是做减法运算,然后判别标志位。EMC单片机没有CMP比较指令,可是咱们经过减法指令能够到达意图,从实质上说,那是共同的。
由于这些逻辑判别是固定的,并且比较繁琐,简单犯错,所以是主张做成宏调用,这样跟其他单片机上面的 CMP指令是相同运用的,比较便利。
(1)A>B
A-B >0 咱们一定要着重次序,也便是说,谁减去谁 的问题,不能搞乱。A-B操作之后PSW的标志位状况
C=1表明没有借位,Z=0 表明成果不为0
(2)A=B
C=1 表明没有借位,Z=1表明成果为0
(3)A
C=0 表明借位,Z=0表明成果不为0
那么很简单推导出别的两个常用的联系:
(4)A >= B
C=1 或许 Z=1,经过Z能判别是否持平。
(5)A <= B
显着这儿是或联系C =0 或许 Z=1 都满意条件判别。
(6)A != B
很简单,只需求 Z=1 就能满意要求
依据这5个联系,写成5个常用的宏,将给程序编写带来非常大的便利。详细完成代码在EMCLIB库里边/arch/generic.dt里边。