當(dāng)前位置:自動(dòng)化網(wǎng)>北京飛旭科技有限公司門(mén)戶(hù)>應(yīng)用案例>ARM中C和匯編混合編程及示例

          ARM中C和匯編混合編程及示例

          發(fā)布時(shí)間:2010-07-19 13:41   類(lèi)型:專(zhuān)業(yè)論文   人瀏覽

           參數(shù)的傳遞規(guī)則.

               根據(jù)參數(shù)個(gè)數(shù)是否固定,可以將子程序分為參數(shù)個(gè)數(shù)固定的子程序和參數(shù)個(gè)數(shù)可變的子程序.這兩種子程序的參數(shù)傳遞規(guī)則是不同的.

               1.參數(shù)個(gè)數(shù)可變的子程序參數(shù)傳遞規(guī)則

               對(duì)于參數(shù)個(gè)數(shù)可變的子程序,當(dāng)參數(shù)不超過(guò)4個(gè)時(shí),可以使用寄存器R0~R3來(lái)進(jìn)行參數(shù)傳遞,當(dāng)參數(shù)超過(guò)4個(gè)時(shí),還可以使用數(shù)據(jù)棧來(lái)傳遞參數(shù). 在參數(shù)傳遞時(shí),將所有參數(shù)看做是存放在連續(xù)的內(nèi)存單元中的字?jǐn)?shù)據(jù)。然后,依次將各名字?jǐn)?shù)據(jù)傳送到寄存器R0,R1,R2,R3; 如果參數(shù)多于4個(gè),將剩余的字?jǐn)?shù)據(jù)傳送到數(shù)據(jù)棧中,入棧的順序與參數(shù)順序相反,即最后一個(gè)字?jǐn)?shù)據(jù)先入棧. 按照上面的規(guī)則,一個(gè)浮點(diǎn)數(shù)參數(shù)可以通過(guò)寄存器傳遞,也可以通過(guò)數(shù)據(jù)棧傳遞,也可能一半通過(guò)寄存器傳遞,另一半通過(guò)數(shù)據(jù)棧傳遞.

               2.參數(shù)個(gè)數(shù)固定的子程序參數(shù)傳遞規(guī)則

               對(duì)于參數(shù)個(gè)數(shù)固定的子程序,參數(shù)傳遞與參數(shù)個(gè)數(shù)可變的子程序參數(shù)傳遞規(guī)則不同,如果系統(tǒng)包含浮點(diǎn)運(yùn)算的硬件部件,浮點(diǎn)參數(shù)將按照下面的規(guī)則傳遞: 各個(gè)浮點(diǎn)參數(shù)按順序處理;為每個(gè)浮點(diǎn)參數(shù)分配FP寄存器;分配的方法是,滿足該浮點(diǎn)參數(shù)需要的且編號(hào)最小的一組連續(xù)的FP寄存器.第一個(gè)整數(shù)參數(shù)通過(guò)寄存器R0~R3來(lái)傳遞,其他參數(shù)通過(guò)數(shù)據(jù)棧傳遞.

               子程序結(jié)果返回規(guī)則

               1.結(jié)果為一個(gè)32位的整數(shù)時(shí),可以通過(guò)寄存器R0返回.

               2.結(jié)果為一個(gè)64位整數(shù)時(shí),可以通過(guò)R0和R1返回,依此類(lèi)推.

               3.結(jié)果為一個(gè)浮點(diǎn)數(shù)時(shí),可以通過(guò)浮點(diǎn)運(yùn)算部件的寄存器f0,d0或者s0來(lái)返回.

               4.結(jié)果為一個(gè)復(fù)合的浮點(diǎn)數(shù)時(shí),可以通過(guò)寄存器f0-fN或者d0~dN來(lái)返回.

               5.對(duì)于位數(shù)更多的結(jié)果,需要通過(guò)調(diào)用內(nèi)存來(lái)傳遞.

          本文通過(guò)幾個(gè)簡(jiǎn)單的例子演示了嵌入式開(kāi)發(fā)中常用的C和匯編混合編程的一些方法和基本的思路,其實(shí)最核心的問(wèn)題就是如何在C和匯編之間傳值,剩下的問(wèn)題就是各自用自己的方式來(lái)進(jìn)行處理。

            
              在嵌入式系統(tǒng)開(kāi)發(fā)中,目前使用的主要編程語(yǔ)言是C和匯編,C++已經(jīng)有相應(yīng)的編譯器,但是現(xiàn)在使用還是比較少的。在稍大規(guī)模的嵌入式軟件中,例如含有OS,大部分的代碼都是用C編寫(xiě)的,主要是因?yàn)镃語(yǔ)言的結(jié)構(gòu)比較好,便于人的理解,而且有大量的支持庫(kù)。盡管如此,很多地方還是要用到匯編語(yǔ)言,例如開(kāi)機(jī)時(shí)硬件系統(tǒng)的初始化,包括CPU狀態(tài)的設(shè)定,中斷的使能,主頻的設(shè)定,以及RAM的控制參數(shù)及初始化,一些中斷處理方面也可能涉及匯編。另外一個(gè)使用匯編的地方就是一些對(duì)性能非常敏感的代碼塊,這是不能依靠C編譯器的生成代碼,而要手工編寫(xiě)匯編,達(dá)到優(yōu)化的目的。而且,匯編語(yǔ)言是和CPU的指令集緊密相連的,作為涉及底層的嵌入式系統(tǒng)開(kāi)發(fā),熟練對(duì)應(yīng)匯編語(yǔ)言的使用也是必須的。
          單純的C或者匯編編程請(qǐng)參考相關(guān)的書(shū)籍或者手冊(cè),這里主要討論C和匯編的混合編程,包括相互之間的函數(shù)調(diào)用。下面分四種情況來(lái)進(jìn)行討論,暫不涉及C++。
          1. 在C語(yǔ)言中內(nèi)嵌匯編
          在C中內(nèi)嵌的匯編指令包含大部分的ARM和Thumb指令,不過(guò)其使用與匯編文件中的指令有些不同,存在一些限制,主要有下面幾個(gè)方面:
           
          a. 不能直接向PC寄存器賦值,程序跳轉(zhuǎn)要使用B或者BL指令
          b. 在使用物理寄存器時(shí),不要使用過(guò)于復(fù)雜的C表達(dá)式,避免物理寄存器沖突
          c. R12和R13可能被編譯器用來(lái)存放中間編譯結(jié)果,計(jì)算表達(dá)式值時(shí)可能將R0到R3、R12及R14用于子程序調(diào)用,因此要避免直接使用這些物理寄存器
          d. 一般不要直接指定物理寄存器,而讓編譯器進(jìn)行分配
          內(nèi)嵌匯編使用的標(biāo)記是 __asm或者asm關(guān)鍵字,用法如下:
          __asm
          {
          instruction [; instruction]

          [instruction]
          }
          asm(“instruction [; instruction]”);
          下面通過(guò)一個(gè)例子來(lái)說(shuō)明如何在C中內(nèi)嵌匯編語(yǔ)言,
          #include <stdio.h>
           
          void my_strcpy(const char *src, char *dest)
          {
          char ch;
           
          __asm
          {
          loop:
          ldrb ch, [src], #1
          strb ch, [dest], #1
          cmp ch, #0
          bne loop
          }
          }
           
          int main()
          {
          char *a = "forget it and move on!";
          char b[64];
           
          my_strcpy(a, b);
          printf("original: %s", a);
          printf("copyed: %s", b);
          return 0;
          }
          在這里C和匯編之間的值傳遞是用C的指針來(lái)實(shí)現(xiàn)的,因?yàn)橹羔槍?duì)應(yīng)的是地址,所以匯編中也可以訪問(wèn)。
           
          2. 在匯編中使用C定義的全局變量
          內(nèi)嵌匯編不用單獨(dú)編輯匯編語(yǔ)言文件,比較簡(jiǎn)潔,但是有諸多限制,當(dāng)匯編的代碼較多時(shí)一般放在單獨(dú)的匯編文件中。這時(shí)就需要在匯編和C之間進(jìn)行一些數(shù)據(jù)的傳遞,最簡(jiǎn)便的辦法就是使用全局變量。
          /* cfile.c
          * 定義全局變量,并作為主調(diào)程序
          */
           
          #include <stdio.h>
          int gVar_1 = 12;
          extern asmDouble(void);
           
          int main()
          {
          printf("original value of gVar_1 is: %d", gVar_1);
          asmDouble();
          printf(" modified value of gVar_1 is: %d", gVar_1);
          return 0;
          }
           
          對(duì)應(yīng)的匯編語(yǔ)言文件
          ;called by main(in C),to double an integer, a global var defined in C is used.
           
          AREA asmfile, CODE, READONLY
           
          EXPORT asmDouble
          IMPORT gVar_1
           
          asmDouble
          ldr r0, =gVar_1
          ldr r1, [r0]
          mov r2, #2
          mul r3, r1, r2
          str r3, [r0]
          mov pc, lr
          END
           
          3. 在C中調(diào)用匯編的函數(shù)
          在C中調(diào)用匯編文件中的函數(shù),要做的主要工作有兩個(gè),一是在C中聲明函數(shù)原型,并加extern關(guān)鍵字;二是在匯編中用EXPORT導(dǎo)出函數(shù)名,并用該函數(shù)名作為匯編代碼段的標(biāo)識(shí),最后用mov pc, lr返回。然后,就可以在C中使用該函數(shù)了。從C的角度,并不知道該函數(shù)的實(shí)現(xiàn)是用C還是匯編。更深的原因是因?yàn)镃的函數(shù)名起到表明函數(shù)代碼起始地址的左右,這個(gè)和匯編的label是一致的。
          /* cfile.c
          * in C,call an asm function, asm_strcpy
          * Sep 9, 2004
          */
          #include <stdio.h>
          extern void asm_strcpy(const char *src, char *dest);
           
          int main()
          {
          const char *s = "seasons in the sun";
          char d[32];
          asm_strcpy(s, d);
          printf("source: %s", s);
          printf(" destination: %s",d);
          return 0;
          }
           
          ;asm function implementation
          AREA asmfile, CODE, READONLY
          EXPORT asm_strcpy
           
          asm_strcpy
          loop
          ldrb r4, [r0], #1 ;address increment after read
          cmp r4, #0
          beq over
          strb r4, [r1], #1
          b loop
          over
          mov pc, lr
          END
          在這里,C和匯編之間的參數(shù)傳遞是通過(guò)ATPCS(ARM Thumb Procedure Call Standard)的規(guī)定來(lái)進(jìn)行的。簡(jiǎn)單的說(shuō)就是如果函數(shù)有不多于四個(gè)參數(shù),對(duì)應(yīng)的用R0-R3來(lái)進(jìn)行傳遞,多于4個(gè)時(shí)借助棧,函數(shù)的返回值通過(guò)R0來(lái)返回。
          4. 在匯編中調(diào)用C的函數(shù)
          在匯編中調(diào)用C的函數(shù),需要在匯編中IMPORT 對(duì)應(yīng)的C函數(shù)名,然后將C的代碼放在一個(gè)獨(dú)立的C文件中進(jìn)行編譯,剩下的工作由連接器來(lái)處理。
          ;the details of parameters transfer comes from ATPCS
          ;if there are more than 4 args, stack will be used
           
          EXPORT asmfile
          AREA asmfile, CODE, READONLY
          IMPORT cFun
           
          ENTRY
          mov r0, #11
          mov r1, #22
          mov r2, #33
          BL cFun
          END
           
          /*C file, called by asmfile */
           
          int cFun(int a, int b, int c)
          {
          return a + b + c;
          }
          在匯編中調(diào)用C的函數(shù),參數(shù)的傳遞也是通過(guò)ATPCS來(lái)實(shí)現(xiàn)的。需要指出的是當(dāng)函數(shù)的參數(shù)個(gè)數(shù)大于4時(shí),要借助stack,具體見(jiàn)ATPCS規(guī)范。
           
          小結(jié)
          以上通過(guò)幾個(gè)簡(jiǎn)單的例子演示了嵌入式開(kāi)發(fā)中常用的C和匯編混合編程的一些方法和基本的思路,其實(shí)最核心的問(wèn)題就是如何在C和匯編之間傳值,剩下的問(wèn)題就是各自用自己的方式來(lái)進(jìn)行處理。以上只是拋磚引玉,更詳細(xì)和復(fù)雜的使用方法要結(jié)合實(shí)際應(yīng)用并參考相關(guān)的資料。
           
          說(shuō)明
          以上代碼在ADS 1.2的工程中編譯,并在對(duì)應(yīng)的AXD中軟件仿真通過(guò)。

          更多內(nèi)容請(qǐng)登陸:http://www.fly-sun.com.cn

















































































































































          本文地址:http://ca800.com/apply/d_1nrutga2l1luk_1.html

          拷貝地址

          版權(quán)聲明:版權(quán)歸中國(guó)自動(dòng)化網(wǎng)所有,轉(zhuǎn)載請(qǐng)注明出處!

          留言反饋
          • 評(píng)價(jià):

          • 關(guān)于:

          • 聯(lián)系人:

          • 聯(lián)系電話:

          • 聯(lián)系郵箱:

          • 需求意向:

          • 驗(yàn)證碼:

            看不清楚?

          主站蜘蛛池模板: 国产中文字幕一区| 男男gay做爽爽免费视频| 国色天香论坛视频高清在线| 久久亚洲av无码精品色午夜| 欧美白人最猛性xxxxx欧美馆| 啦啦啦手机完整免费高清观看 | 亚洲一区欧洲一区| 男性gay黄免费网站| 国产亚洲精品aa片在线观看网站 | 国产成人做受免费视频| 99久久综合狠狠综合久久| 成年人视频在线免费播放| 久热青青青在线视频精品| 欧美老熟妇又粗又大| 午夜精品福利在线观看| 韩国精品福利一区二区三区| 国产精品国产精品国产专区不卡| igao在线观看| 成年女人视频网站免费m| 久久青青草原亚洲av无码麻豆| 永久免费无内鬼放心开车| 再深点灬舒服灬太大了免费视频| 车文里的冰块棉签是干啥用的| 国产福利在线导航| 97欧美精品激情在线观看最新 | 俄罗斯乱理伦片在线观看| 色噜噜狠狠狠狠色综合久一| 国产成人精品美女在线| 2022国产成人福利精品视频| 天天爱天天色天天干| 中文乱码字幕午夜无线观看 | 四虎成人精品在永久免费| 黑人26厘米大战亚洲女| 国产精品嫩草影院永久一| 99久久国产综合精品成人影院| 少妇精品久久久一区二区三区| 久久99精品久久水蜜桃| 日韩在线观看视频免费| 亚洲sss视频| 欧美在线看片a免费观看| 亚洲毛片av日韩av无码|