新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 單片機(jī)的加減法原理

單片機(jī)的加減法原理

作者: 時(shí)間:2016-11-17 來源:網(wǎng)絡(luò) 收藏
這是計(jì)算機(jī)組成原理的問題。計(jì)算機(jī)怎么表示負(fù)數(shù)。最高位為0,表示正數(shù),最高位為1表示負(fù)數(shù),例如

0b 0000 0011 表示 +3

本文引用地址:http://butianyuan.cn/article/201611/315476.htm

0b 1111 1111 表示 -1

所以,那么數(shù)值的取值范圍就是這么來的,一個(gè)字節(jié)有8位,如果是無符號數(shù),那么就能表示 0~255 一共 256個(gè)數(shù),但是如果是有符號數(shù),也就是說這8位里面還需要表示一個(gè)符號,而且負(fù)號在最高位,那么數(shù)值只能是 bit0 ~ bit 7 表示,也就是說 -128 ~ 127

計(jì)算機(jī)里面做的運(yùn)算都是補(bǔ)碼運(yùn)算,有符號數(shù)還是無符號數(shù),計(jì)算機(jī)是不管的,其實(shí)這個(gè)只是寫給編譯器看的,由編譯器去識別。并且生成相對應(yīng)的代碼。

原碼,反碼,補(bǔ)碼的變換

原碼,本來的數(shù)據(jù)叫原碼,反碼是各位取反,補(bǔ)碼有具體的運(yùn)算規(guī)則。

例如signed char 類型的數(shù)據(jù) +3

原碼 0b 0000 0011 最高位為0,表示正數(shù)。

反碼 0b 1111 1100 很簡單,各位取反。

補(bǔ)碼運(yùn)算規(guī)則

1, 如果是正數(shù),那么補(bǔ)碼=原碼

2, 如果是負(fù)數(shù),那么補(bǔ)碼=原碼的反碼+1

上面例子,+3的補(bǔ)碼為 0b 0000 0011 ,和原碼一樣。

如果換成 -3 那么情況就是

0000 0011 à 1111 1100 + 1 à 1111 1101 這個(gè)就是 -3 的補(bǔ)碼,計(jì)算機(jī)就是這樣表示負(fù)數(shù)的。

于是今天研究了一下EMC單片機(jī)的加減運(yùn)算

由于是用匯編寫的,那么就壓根沒有所謂的有符號數(shù)和無符號數(shù)的區(qū)別。所以程序里面可以認(rèn)為的認(rèn)定,也就是我,我認(rèn)為是他有符號,還是無符號。最麻煩的就是越界問題,數(shù)據(jù)過大溢出了。但是只需要記住一點(diǎn),單片機(jī)電路是按照補(bǔ)碼運(yùn)算的,依稀的記憶中想起了當(dāng)年數(shù)字電路課程里面出現(xiàn)的東西,不過記憶已經(jīng)很模糊了。得復(fù)習(xí)一下。

最重要的是:計(jì)算機(jī)里面都是按照補(bǔ)碼來運(yùn)算的??!這是由數(shù)字邏輯電路決定的。

怎么和 C 進(jìn)位聯(lián)合起來。于是我想從幾種情況分析。

1, 加法的情況,2+3 = 5 ,只要是智力沒有問題的都不會(huì)算錯(cuò)吧 ……

單片機(jī)里面的情況,我們認(rèn)為這個(gè)是有符號數(shù),那么就是2個(gè)正數(shù)相加,

這里要注意的,“我當(dāng)他是有符號數(shù)”是我人為加以假設(shè),單片機(jī)可不吃這一套,反正,只要執(zhí)行 mov 指令將數(shù)據(jù)送到單片機(jī),那么單片機(jī)就認(rèn)為這是補(bǔ)碼,他可不管你有沒有符號。

那么過程是這樣:

大腦里面人為這兩個(gè)是補(bǔ)碼,那么根據(jù)補(bǔ)碼的運(yùn)算規(guī)則,正數(shù)的補(bǔ)碼就是原碼,得到

0000 0010

+ 0000 0011

--------------------------

0000 0101

進(jìn)位 C=0 表示加法沒有溢出。

這就是單片機(jī)的運(yùn)算結(jié)果了。

單片機(jī)就是得到這個(gè)東西,這個(gè)是一個(gè)補(bǔ)碼,因?yàn)閱纹瑱C(jī)只認(rèn)識補(bǔ)碼,其他他不認(rèn)識。那么然后我們將做小處理。

如果我們大腦將他看成是無符號數(shù),那么這里表示的是 5 ,如果我們將他看成有符號數(shù),那么這里表示的就是 +5 (因?yàn)樽罡呶粸?,原碼和補(bǔ)碼相同)

2, 如果兩個(gè)數(shù)據(jù)比較大,相加會(huì)溢出,這怎么處理。0xff+0xff = ?

1111 1111

+ 1111 1111

--------------------------

1 1111 1110

進(jìn)位 C=1 表示加法運(yùn)算有進(jìn)位。

那么其實(shí)這里表示的是 FF + FF =1FE ,C代表最高位,跟普通加法運(yùn)算是一樣的,因?yàn)橛?jì)算機(jī)當(dāng)成補(bǔ)碼,他不管你什么數(shù),他就按照補(bǔ)碼運(yùn)算。

3, 減法運(yùn)算,差是正數(shù): 3-2 = 1

前面加法,補(bǔ)碼基本上沒啥出場機(jī)會(huì),但是減法就不同,減法就是補(bǔ)碼發(fā)揮作用的時(shí)候。記以前數(shù)字電路的老師說過,數(shù)字電路只有加法器(全加器和半加器),是沒有減法器的,所以計(jì)算機(jī)對待減法運(yùn)算,實(shí)際上是用加法運(yùn)算代替的。那么

3-2 可以轉(zhuǎn)化為 3+(-2) 這個(gè)就是加法運(yùn)算了。然后考慮兩個(gè)數(shù)的補(bǔ)碼。3為正數(shù),所以補(bǔ)碼為原碼本身,-2 為負(fù)數(shù),補(bǔ)碼為反碼后再加1,那么加過是

3 :0011

-2 :1110

那么 3-2 單片機(jī)運(yùn)算的結(jié)果,實(shí)際上相當(dāng)于 0011 + 1110 的結(jié)果,是

0000 0011

+ 1111 1110

--------------------------

1 0000 0001

C=1表示減法沒有借位,結(jié)果為 00000001,這是一個(gè)補(bǔ)碼,因此這個(gè)是正數(shù),所以原碼是他本身,也即是說結(jié)果為 1 ,沒有錯(cuò)位,也就是說 被減數(shù)大于減數(shù)。

EMC單片機(jī)的代碼是:

mov a,@3

mov 0x20,a

mov a,@2

sub 0x20,a

0x20存放最終結(jié)果,仿真運(yùn)行結(jié)果,0x20數(shù)值為 1,C=1表示沒有借位,Z=0表示運(yùn)算結(jié)果非零。這個(gè)跟我們分析的完全吻合。

我們推廣一下:

既然我們說了 3-2 最終會(huì)被計(jì)算機(jī)轉(zhuǎn)化為補(bǔ)碼加法,那么我將上面的EMC單片機(jī)的代碼手工做成加法,那么期待得到的結(jié)果應(yīng)該是一樣的。

mov a,@3

mov 0x20,a

mov a,@0xfe

add 0x20,a

仿真運(yùn)行結(jié)果,0x20數(shù)值為 1,C=1表示加法運(yùn)算進(jìn)位了,Z=0表示運(yùn)算結(jié)果非零。這個(gè)跟上面的減法運(yùn)算結(jié)果是一模一樣的。這就是我們期待的結(jié)果,證明了單片機(jī)里面是補(bǔ)碼的運(yùn)算。

4, 減法運(yùn)算,差是負(fù)數(shù),也就是說不夠減,例如 2-3 = -1

這個(gè)運(yùn)算在單片機(jī)里面究竟是怎么進(jìn)行的呢?其實(shí)也很簡單,記住我們的信條:“單片機(jī)里面都是補(bǔ)碼運(yùn)算”那么很自然的化成 2 + (-3),求出 2 和 -3的補(bǔ)碼并進(jìn)行運(yùn)算

0000 0010

+ 1111 1101

--------------------------

0 1111 1111

進(jìn)位位C = 0表示減法運(yùn)算發(fā)生錯(cuò)位,結(jié)果是 0b11111111,這就是最終結(jié)果了。

但是這個(gè)值我們要看的懂,必須變化為原碼,說過了,這是一個(gè)補(bǔ)碼,最高位為1表示這是一個(gè)負(fù)數(shù),所以求原碼的辦法,也是將補(bǔ)碼取反再加一,也就是

0b11111111 à 0b00000000+1 à 0b00000001

這個(gè)就是我們最終的結(jié)果,是一個(gè)負(fù)數(shù),絕對值為1,也就是說結(jié)果為 -1

這跟我們期待的結(jié)果是一模一樣的。EMC單片機(jī)仿真代碼以及結(jié)果:

mov a,@2

mov 0x20,a

mov a,@3

sub 0x20,a

寄存器0x20的值為 0xff,進(jìn)位C=0表示減法發(fā)生了錯(cuò)位,Z=0表示結(jié)果非零。

這完全和我們分析的吻合。再強(qiáng)調(diào),單片機(jī)里面出現(xiàn)的都是補(bǔ)碼,所以這結(jié)果的 0xff 也是補(bǔ)碼,想看懂得轉(zhuǎn)化為原碼。上面已經(jīng)說了轉(zhuǎn)化辦法。

另外,我們需要分開來看,我們上面是說將這個(gè)數(shù)字看成是“有符號數(shù)”,2-3=-1這個(gè)是我們要的結(jié)果,但是,如果我們把這個(gè)數(shù)看成是“無符號數(shù)”那又該怎么辦呢?

辦法就是,借位,跟我們手工減法一樣,不夠減就向高位借位。

2-3 = 0010 – 0011 這是不夠減的,那么 2應(yīng)該向高位借一,變成 10010 – 0011 = 1111,這里扮演高位的其實(shí)就是進(jìn)位C,也就是說C=0時(shí)是發(fā)生錯(cuò)位的,為什么?因?yàn)檫@個(gè)C=1被被減數(shù)借去用了,結(jié)果為 0xff ,這個(gè)時(shí)候 0xff 就是我們想要的結(jié)果,不需要變化,因?yàn)槲覀儾皇强闯捎蟹枖?shù)。

5, 兩個(gè)數(shù)比較大小 CMP A , B

兩個(gè)數(shù)比較大小,記得以前微機(jī)原理的老師給我們說了,本質(zhì)就是做減法運(yùn)算,然后判斷標(biāo)志位。EMC單片機(jī)沒有CMP比較指令,但是我們通過減法指令可以達(dá)到目的,從本質(zhì)上說,那是一致的。

因?yàn)檫@些邏輯判斷是固定的,而且比較繁瑣,容易出錯(cuò),所以是建議做成宏調(diào)用,這樣跟其他單片機(jī)上面的 CMP指令是一樣使用的,比較方便。

(1)A>B

A-B >0 我們一定要強(qiáng)調(diào)順序,也就是說,誰減去誰 的問題,不能搞亂。A-B操作之后PSW的標(biāo)志位狀態(tài)

C=1表示沒有借位,Z=0 表示結(jié)果不為0

(2)A=B

C=1 表示沒有借位,Z=1表示結(jié)果為0

(3)A

C=0 表示借位,Z=0表示結(jié)果不為0

那么很簡單推導(dǎo)出另外兩個(gè)常用的關(guān)系:

(4)A >= B

C=1 或者 Z=1,通過Z能判斷是否相等。

(5)A <= B

明顯這里是或關(guān)系C =0 或者 Z=1 都滿足條件判斷。

(6)A != B

很簡單,只需要 Z=1 就能滿足要求

根據(jù)這5個(gè)關(guān)系,寫成5個(gè)常用的宏,將給程序編寫帶來非常大的方便。具體實(shí)現(xiàn)代碼在EMCLIB庫里面/arch/generic.dt里面。



關(guān)鍵詞: 單片機(jī)加減法原

評論


技術(shù)專區(qū)

關(guān)閉