在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 硬件堆棧和軟件堆棧在AVR中的理解

            硬件堆棧和軟件堆棧在AVR中的理解

            作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò) 收藏
            首先是從理論上的東西。。網(wǎng)上轉(zhuǎn)載來(lái)的,后面是看AVR代碼時(shí)得出的一些東西。

            硬件堆棧:或許也可以稱(chēng)作系統(tǒng)堆棧,是位于片內(nèi)RAM區(qū)。有人說(shuō),只要能使用PUSH,POP指令的單片機(jī),都可以說(shuō)含有硬件堆棧。這樣的說(shuō)法我個(gè)人覺(jué)得不是很全面。通過(guò)指令進(jìn)行壓棧和出棧操作只是系統(tǒng)堆棧中的一種操做。系統(tǒng)堆棧還可以被隱含調(diào)用。例如,當(dāng)調(diào)用子程序時(shí),系統(tǒng)會(huì)主動(dòng)把返回地址壓入堆棧,并不需要用戶(hù)通過(guò)指令操作。通常,棧底設(shè)在內(nèi)存的高端,也就是把內(nèi)存的最高一段空間劃作棧區(qū)。這些都是向下生長(zhǎng)棧。棧指針可能是專(zhuān)用的寄存器,也可能借用一通用寄存器。也有單片機(jī)是在數(shù)據(jù)區(qū)里劃一塊作棧區(qū),可能是向上生長(zhǎng),也可能是向下生長(zhǎng)。

            本文引用地址:http://www.biyoush.com/article/201611/320152.htm

            硬件堆棧:是通過(guò)寄存器SPH,SPL做為索引指針的地址,是調(diào)用了CALL,RCALL等函數(shù)調(diào)用指令后硬件自動(dòng)填充的堆棧!

            軟件堆棧:是編譯器為了處理一些參數(shù)傳遞而做的堆棧,會(huì)由編譯器自動(dòng)產(chǎn)生和處理,可以通過(guò)相應(yīng)的編譯選項(xiàng)對(duì)其進(jìn)行編輯。

            簡(jiǎn)單一點(diǎn)說(shuō),硬件堆棧主要做為地址堆棧用,而軟件堆棧主要會(huì)被分配成數(shù)據(jù)堆棧!

            ---摘自《AVR單片機(jī)C語(yǔ)言開(kāi)發(fā)入門(mén)指導(dǎo)》-P169---
            ICCAVR使用兩個(gè)堆棧:一個(gè)用于子程序調(diào)用和中斷操作的硬件堆棧,一個(gè)用于傳遞參數(shù)、臨時(shí)變量和局部變量的軟件堆棧??梢允褂枚褩z測(cè)函數(shù)檢測(cè)兩個(gè)堆棧是否溢出。

            如果沒(méi)有硬堆棧,你可以選定一個(gè)寄存器作堆棧指針,通過(guò)軟件實(shí)現(xiàn)堆棧操作。移植μC/OS-II也不一定要硬堆棧。ARM 就很難說(shuō)它的堆棧是軟的還是硬的。32位的ARM指令中沒(méi)有PUSH、POP指令。ARM習(xí)慣上用R13作堆棧指針(SP),但用別的寄存器作堆棧指針也未常不可。ARM習(xí)慣上用LDM/STM(多寄存器加載/存儲(chǔ)指令)來(lái)操作堆棧,壓多少,按什么順序都能選擇。應(yīng)該說(shuō)ARM是軟硬結(jié)合的堆棧。

            C代碼(AVR-GCC編譯,優(yōu)化等級(jí)-00):

            #include <avr/io.h>

            int add(int a,int b)
            {
            int c;
            c=a+b;
            return c;
            }

            int main(void)
            {
            int a=2,b=3,c=0;

            c=add(a,b);
            //c=sub(a,b);
            }
            匯編代碼:

            (省略一些boot代碼)

            。。。。。。。

            00000054 <__ctors_end>:
            54: 11 24 eor r1, r1
            56: 1f be out 0x3f, r1 ; 63
            58: cf e5 ldi r28, 0x5F ; 95 //此處Y指針和SP都指到了SRAM最高端
            5a: d4 e0 ldi r29, 0x04 ; 4
            5c: de bf out 0x3e, r29 ; 62
            5e: cd bf out 0x3d, r28 ; 61

            。。。

            0000008e :
            #include

            int add(int a,int b)
            {
            8e: cf 93 push r28
            90: df 93 push r29 //保存了Y指針,此時(shí)SP已經(jīng)-2,這里再減2
            92: cd b7 in r28, 0x3d ; 61 //重新定位Y指針跟SP一樣。
            94: de b7 in r29, 0x3e ; 62
            96: 26 97 sbiw r28, 0x06 ; 6 //減掉6,即向下開(kāi)了6字節(jié)的區(qū)域,存放3變量
            98: 0f b6 in r0, 0x3f ; 63
            9a: f8 94 cli
            9c: de bf out 0x3e, r29 ; 62
            9e: 0f be out 0x3f, r0 ; 63
            a0: cd bf out 0x3d, r28 ; 61
            a2: 9a 83 std Y+2, r25 ; 0x02
            a4: 89 83 std Y+1, r24 ; 0x01
            a6: 7c 83 std Y+4, r23 ; 0x04
            a8: 6b 83 std Y+3, r22 ; 0x03
            int c;
            c=a+b;
            aa: 29 81 ldd r18, Y+1 ; 0x01
            ac: 3a 81 ldd r19, Y+2 ; 0x02
            ae: 8b 81 ldd r24, Y+3 ; 0x03
            b0: 9c 81 ldd r25, Y+4 ; 0x04
            b2: 82 0f add r24, r18
            b4: 93 1f adc r25, r19
            b6: 9e 83 std Y+6, r25 ; 0x06
            b8: 8d 83 std Y+5, r24 ; 0x05
            return c;
            ba: 8d 81 ldd r24, Y+5 ; 0x05
            bc: 9e 81 ldd r25, Y+6 ; 0x06
            be: 26 96 adiw r28, 0x06 ; 6 //加了6個(gè)字節(jié)空間,Y指針恢復(fù)到減6之前
            c0: 0f b6 in r0, 0x3f ; 63
            c2: f8 94 cli
            c4: de bf out 0x3e, r29 ; 62
            c6: 0f be out 0x3f, r0 ; 63
            c8: cd bf out 0x3d, r28 ; 61
            ca: df 91 pop r29
            cc: cf 91 pop r28
            ce: 08 95 ret //彈出堆棧中2個(gè)字節(jié)

            000000d0

            :
            }

            int main(void)
            {
            d0: c9 e5 ldi r28, 0x59 ; 89 //這4句給SP和Y指針重新賦值了,很明顯的在SP的
            d2: d4 e0 ldi r29, 0x04 ; 4 //上面還有6個(gè)字節(jié)(SRAM最大到045E),這6個(gè)字節(jié)
            d4: de bf out 0x3e, r29 ; 62 //被存放了a,b,c三個(gè)變量(可以與上面理論對(duì)應(yīng))
            d6: cd bf out 0x3d, r28 ; 61 //通過(guò)Y指針來(lái)保存了這三個(gè)變量到這個(gè)區(qū)域
            int a=2,b=3,c=0;
            d8: 82 e0 ldi r24, 0x02 ; 2
            da: 90 e0 ldi r25, 0x00 ; 0
            dc: 9a 83 std Y+2, r25 ; 0x02
            de: 89 83 std Y+1, r24 ; 0x01
            e0: 83 e0 ldi r24, 0x03 ; 3
            e2: 90 e0 ldi r25, 0x00 ; 0
            e4: 9c 83 std Y+4, r25 ; 0x04
            e6: 8b 83 std Y+3, r24 ; 0x03
            e8: 1e 82 std Y+6, r1 ; 0x06
            ea: 1d 82 std Y+5, r1 ; 0x05

            c=add(a,b);
            ec: 6b 81 ldd r22, Y+3 ; 0x03
            ee: 7c 81 ldd r23, Y+4 ; 0x04
            f0: 89 81 ldd r24, Y+1 ; 0x01
            f2: 9a 81 ldd r25, Y+2 ; 0x02
            f4: 0e 94 47 00 call 0x8e //使用call時(shí)自動(dòng)將PC+2的地址壓到堆棧
            f8: 9e 83 std Y+6, r25 ; 0x06
            fa: 8d 83 std Y+5, r24 ; 0x05
            //c=sub(a,b);
            }
            fc: 80 e0 ldi r24, 0x00 ; 0
            fe: 90 e0 ldi r25, 0x00 ; 0
            100: 0c 94 82 00 jmp 0x104 <_exit>

            00000104 <_exit>:
            104: ff cf rjmp .-2 ; 0x104 <_exit>

            r28和r29一起組成SP指針,Y指針可以作為間接尋址,很明顯的剛開(kāi)始的時(shí)候Y指針和SP都在045F這里,后來(lái)在高處開(kāi)了6個(gè)字節(jié)的空間來(lái)存放臨時(shí)變量,所以Y指針成了這個(gè)軟件堆棧的棧頂,在這個(gè)過(guò)程中都是使用Y和SP的配合來(lái)實(shí)現(xiàn)變量和數(shù)據(jù)的改變,以及恢復(fù),硬件堆棧和軟件堆棧在這里已經(jīng)不怎么區(qū)分了。。。不清楚流程可以畫(huà)個(gè)圖來(lái)加深理解,好了,看了那么久,總算有點(diǎn)感覺(jué)了。。



            關(guān)鍵詞: 硬件堆棧軟件堆棧AV

            評(píng)論


            技術(shù)專(zhuān)區(qū)

            關(guān)閉