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

<s id="cmphk"><label id="cmphk"></label></s>
    <span id="cmphk"><var id="cmphk"></var></span>
    <dfn id="cmphk"><var id="cmphk"></var></dfn>
    <menu id="cmphk"><thead id="cmphk"></thead></menu>

    <address id="cmphk"></address>

      <dfn id="cmphk"></dfn>
      
      
      <span id="cmphk"></span>

      <object id="cmphk"><tt id="cmphk"></tt></object>
      1. 新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 深入剖析keil c51 --- 從匯編到c51

        深入剖析keil c51 --- 從匯編到c51

        作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
        C插入匯編語句
        #pragma asm
        ljmp 0
        #pragma endasm

        如果就這樣直接編譯的話,會出現(xiàn)以下錯誤:
        error C272: asm/endasm requires src-control to be active

        解決方法:在 Files Toolbar 中選中當(dāng)前C51文件,點右鍵查看文件選項,將 Generate Assembler SRC File 與 Assemble SRC File 的勾選由灰色變?yōu)楹谏?,即使這兩項有效!



        第一節(jié)main()函數(shù)和啟動代碼
        匯編是從org 0000h開始啟動,那么keil c51是如何啟動main()函數(shù)的?keil c51有一個啟動程序startup.a51,它總是和c程序一起編譯和鏈接。下面看看它和main()函數(shù)是如何編譯的;
        //主函數(shù)如下;
        void main(void)
        {
        while (1)這是個無條件空循環(huán)。
        {
        }
        }
        把上面的main()函數(shù)編譯后的匯編程序和反匯編代碼整理后對照如下;
        ?C_C51STARTUPSEGMENTCODE
        ?PR?main?TESTMAINSEGMENT CODE

        ?STACKSEGMENTIDATA

        RSEG?STACK
        DS1

        CSEGAT0
        ?C_STARTUP:LJMPSTARTUP1
        C:0x0000020003LJMPSTARTUP1(C:0003)

        RSEG?C_C51STARTUP
        STARTUP1:;該段程序把內(nèi)存清零
        ;MOVR0,#IDATALEN -1
        C:0x0003787FMOVR0,#0x7F
        ;CLRA
        C:0x0005E4CLRA
        ;MOV@R0,A
        IDATALOOP:
        C:0x0006F6MOV@R0,A
        ;DJNZR0,IDATALOOP
        C:0x0007D8FDDJNZR0,IDATALOOP(C:0006)
        ;MOVSP,#?STACK-1;設(shè)制CPU的堆棧起始地址
        C:0x0009758107MOVSP(0x81),#0x07
        ;LJMP?C_START
        C:0x000C02000FLJMPmain(C:000F)

        RSEG?PR?main?TESTMAIN
        main:
        ;void main(void)
        C:0x000F80FESJMPmain(C:000F);main()函數(shù)

        現(xiàn)在分析上面的匯編程序就會明白c51程序是如何啟動的。
        該程序有三個代碼段;
        第一個代碼段?C_STARTUP在0x0000地址,是CPU第一條指令的入口,它只有一條長跳轉(zhuǎn)指令,直接跳到第二個代碼段.
        第二個代碼段?C_C51STARTUP是可重定位的段,該程序把內(nèi)存清零,然后再設(shè)置CPU的堆棧,最后跳轉(zhuǎn)到main()函數(shù).
        第三個代碼段就是main()函數(shù),在keil c51編譯器里main()的段地址名就是?C_START。

        還有一個IDATA數(shù)據(jù)段?STACK就是堆棧,?STACK用于設(shè)制CPU的堆棧起始地址,這是由keil編譯器自動完成的
        /*******************************************************************/
        keil c51函數(shù)的返回值是存儲在r0-r7中的。
        多字節(jié)變量在存儲器里都是低地址存高位,高地址存低位。
        main()函數(shù)的局部變量都是放在存儲器里的,不象別的函數(shù)先選寄存器r0-r7存放,如果不夠用再存入存儲器里。

        看下面的示例;
        c51程序;
        unsigned int SumXY(unsigned int X,Y);
        void main(void)
        {unsigned int a,b,c;
        a=0x5500;
        b=0xaa;
        while (1)
        {
        c=SumXY(a,b);
        }
        }

        unsigned int SumXY(unsigned int X,Y)
        {unsigned int Z;
        Z=X+Y;
        return Z;
        }

        編譯后的反匯編代碼列表;
        C:0x0000020027LJMPSTARTUP1(C:0027)

        4: void main(void)
        5: {unsigned int a,b,c;
        6:a=0x5500;
        C:0x0003750855MOV0x08,#0x55;ram地址0x08和0x09存放變量a=0x5500。
        C:0x0006750900MOV0x09,#0x00
        7:b=0xaa;
        C:0x0009750A00MOV0x0A,#0x00;ram地址0x0A和0x0B存放變量b=0x00AA。
        C:0x000C750BAAMOV0x0B,#0xAA


        8:while (1)
        9:{
        10:c=SumXY(a,b);
        C:0x000FAD0BMOVR5,0x0B;寄存器R4和R5傳遞變量a的值。
        C:0x0011AC0AMOVR4,0x0A
        C:0x0013AF09MOVR7,0x09;寄存器R6和R7傳遞變量b的值。
        C:0x0015AE08MOVR6,0x08
        C:0x0017120020LCALLSumXY(C:0020);調(diào)用函數(shù)SumXY(a,b)求c=a+b
        C:0x001A8E0CMOV0x0C,R6;函數(shù)SumXY(a,b)返回的整型值存在R6和R7里,
        C:0x001C8F0DMOV0x0D,R7;把返回值存入變量c,ram地址0x0C和0x0D存放變量c
        11:}
        12: }
        13:
        C:0x001E80EFSJMPC:000F


        14: unsigned int SumXY(unsigned int X,Y)
        15: {unsigned int Z;
        16:Z=X+Y;
        C:0x0020EFMOVA,R7;參數(shù)變量X放在寄存器R6和R7里
        C:0x00212DADDA,R5;參數(shù)變量Y放在寄存器R4和R5里
        C:0x0022FFMOVR7,A
        C:0x0023EEMOVA,R6
        C:0x00243CADDCA,R4;計算Z=X+Y;
        C:0x0025FEMOVR6,A;局部變量Z也放在寄存器R6和R7里
        17:return Z;;由寄存器R6和R7里返回函數(shù)的值
        C:0x002622RET


        151:MOVSP,#?STACK-1
        152: ; This code is required if you use L51_BANK.A51 with Banking Mode 4
        153: ; EXTRN CODE (?B_SWITCH0)
        154: ;CALL?B_SWITCH0; init bank mechanism to code bank 0
        C:0x002775810DMOVSP(0x81),#0x0D
        155:LJMP?C_START
        C:0x002A020003LJMPmain(C:0003)

        函數(shù)的入口地址,如何調(diào)用匯編函數(shù),c和匯編的混合編程
        /*******************************************************************/
        c函數(shù)的函數(shù)名是一個指向函數(shù)的指針常量,它的值就是函數(shù)的入口地址。
        從匯編程序上看,函數(shù)名也是該匯編函數(shù)代碼段的入口地址標(biāo)號。
        調(diào)用匯編函數(shù)就是調(diào)用匯編函數(shù)的入口地址標(biāo)號,但是要注意c函數(shù)名和匯編函數(shù)標(biāo)號之間的轉(zhuǎn)換規(guī)則。
        1.不帶參數(shù)的匯編函數(shù)標(biāo)號和c函數(shù)名相同.
        2.帶參數(shù)的匯編函數(shù)標(biāo)號在c函數(shù)名前加字符_,例如;如果c函數(shù)名是SumXY,匯編函數(shù)標(biāo)號是_SumXY
        3.再入函數(shù)的匯編函數(shù)標(biāo)號在c函數(shù)名前加_?,例如;如果c函數(shù)名是DoTask,匯編函數(shù)標(biāo)號是_?DoTask


        程序示例,該例有兩個文件,一個文件是exam1.c,一個文件是funcasm.c
        主程序文件: exam1.c
        extern unsigned int SumXY(unsigned int X,Y);//聲明外部匯編語言函數(shù),和聲明c函數(shù)方法相同。
        extern void Delay(unsigned char T);

        void main(void)
        {unsigned int a,b,c;
        a=0x5500;
        b=0x00aa;
        while (1)
        {
        Delay(100);
        c=SumXY(a,b);
        }
        }

        混合編程文件: funcasm.c

        //c和匯編的混合編程演示.
        //注意要把匯編語言函數(shù)放在文件前面。

        //求Z=X+Y的匯編語言函數(shù),Z,X,Y是整型數(shù)。
        #pragma ASM
        PUBLIC_SumXY
        ?PR?_SumXY?FUNCASMSEGMENT CODE
        RSEG?PR?_SumXY?FUNCASM
        _SumXY:;求Z=X+Y
        MOVA,R7;參數(shù)X放在寄存器R6和R7里
        ADDA,R5;參數(shù)Y放在寄存器R4和R5里
        MOVR7,A
        MOVA,R6
        ADDCA,R4;撲鉠=X+Y;
        MOVR6,A;局部變量Z也放在寄存器R6和R7里
        RET
        #pragma ENDASM


        //c語言函數(shù),延時函數(shù)。
        void Delay(unsigned char T)
        {unsigned char i;
        for (i=0;i{
        for (i=0;i}
        }

        /**********************************************************************/
        上面程序編譯后的反匯編代碼列表;
        C_STARTUP:
        C:0x0000020041LJMPSTARTUP1(C:0041)

        main:
        //給變量a和b賦值a=0x5500;b=0x00aa;
        C:0x0003750855MOV0x08,#0x55
        C:0x0006750900MOV0x09,#0x00
        C:0x0009750A00MOV0x0A,#0x00
        C:0x000C750BAAMOV0x0B,#0xAA

        //調(diào)用延時函數(shù)Delay(100);
        C:0x000F7F64MOVR7,#0x64
        C:0x0011120025LCALLDELAY(C:0025)

        //求c=SumXY(a,b);
        C:0x0014AD0BMOVR5,0x0B
        C:0x0016AC0AMOVR4,0x0A
        C:0x0018AF09MOVR7,0x09
        C:0x001AAE08MOVR6,0x08
        C:0x001C12003ALCALLSUMXY(C:003A);調(diào)用匯編語言函數(shù)SumXY(unsigned int X,Y)
        C:0x001F8E0CMOV0x0C,R6
        C:0x00218F0DMOV0x0D,R7
        C:0x002380EASJMPC:000F


        //c語言延時函數(shù)的反匯編代碼
        //void Delay(unsigned char T)
        DELAY:
        C:0x0025E4CLRA
        C:0x0026FEMOVR6,A
        C0001:
        C:0x0027EEMOVA,R6
        C:0x0028C3CLRC
        C:0x00299FSUBBA,R7
        C:0x002A500DJNCC0007(C:0039)
        C:0x002CE4CLRA
        C:0x002DFEMOVR6,A
        C0004:
        C:0x002EEEMOVA,R6
        C:0x002FC3CLRC
        C:0x00309FSUBBA,R7
        C:0x00315003JNCC0003(C:0036)
        C:0x00330EINCR6
        C:0x003480F8SJMPC0004(C:002E)
        C0003:
        C:0x00360EINCR6
        C:0x003780EESJMPC0001(C:0027)
        C0007:
        C:0x003922RET


        //匯編語言函數(shù)SumXY(unsigned int X,Y)的反匯編代碼,求Z=X+Y
        SUMXY:
        C:0x003AEFMOVA,R7
        C:0x003B2DADDA,R5
        C:0x003CFFMOVR7,A
        C:0x003DEEMOVA,R6
        C:0x003E3CADDCA,R4
        C:0x003FFEMOVR6,A
        C:0x004022RET

        //程序啟動代碼;
        STARTUP1:
        C:0x004175810DMOVSP(0x81),#0x0D
        C:0x0044020003LJMPmain(C:0003)


        參數(shù)傳遞規(guī)則例子:
        fun1(int a)//a是第一個參數(shù),在R6,R7中傳遞.
        fun2(int b ,int c , int *d)//b在R6,R7中傳遞;C在R4,R5中傳遞;d在R1,R2,R3中傳遞.
        fun3(long e ,long f)//e在R4-R7中傳遞;f不能在寄存器中傳遞,只能在參數(shù)傳遞段中傳遞.
        fun3(float g ,char h)//g在R4-R7中傳遞;h不能在寄存器中傳遞,只能在參數(shù)傳遞段中傳遞


        關(guān)鍵詞: keilc51匯

        評論


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

        關(guān)閉
        ×

        “芯”朋友见面大会
        珠海|11.14|泰克“芯”朋友见面大会珠海站|泰克带您从测试角度看半导体的整条产业链,快来报名抢位吧>>