ARM匯編語言程序標準和范例PPT_第1頁
ARM匯編語言程序標準和范例PPT_第2頁
ARM匯編語言程序標準和范例PPT_第3頁
ARM匯編語言程序標準和范例PPT_第4頁
ARM匯編語言程序標準和范例PPT_第5頁
已閱讀5頁,還剩78頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、嵌入式系統(tǒng)原理與開發(fā),第11講 南京大學(xué)計算機系 俞建新主講,2008年春季,2008年10月23日,2,第5章 ARM指令集和匯編語言程序,本章主要介紹以下內(nèi)容: ARM指令集的基本特點 與Thumb指令集的區(qū)別 與x86處理器的區(qū)別 ARM指令格式 ARM尋址方式 ARM指令集分類詳解 ARM匯編語句格式和程序格式 ARM匯編語言的指示符 ARM匯編程序標準與規(guī)范 典型ARM匯編語言程序舉例,2008年10月23日,3,本講主要參考文獻,ARM公司英文資料: ADS_AssemblerGuide_B.pdf DDI0100E_ARM_ARM.pdf 中文圖書 ARM體系結(jié)構(gòu)與編程,清華大學(xué)

2、出版社 嵌入式系統(tǒng)基礎(chǔ)教程,機械工業(yè)出版社,2008年10月23日,4,講授內(nèi)容,ATPCS 和AAPCS規(guī)范要點 ARM編譯器保有的特定關(guān)鍵字 典型ARM匯編語言程序舉例 ARM匯編程序基本結(jié)構(gòu) C程序和CPP程序調(diào)用ARM匯編子程序 ARM匯編程序調(diào)用ARM匯編子程序 整數(shù)除法子程序 S3C44B0X處理器的啟動代碼 44BInit.s、option.s、memcfg.s,2008年10月23日,5,5.7 ARM匯編程序規(guī)范,寄存器的使用規(guī)則 堆棧使用規(guī)則 參數(shù)傳遞規(guī)則,2008年10月23日,6,ATPCS,ATPCS(ARM-Thumb Procedure Call Standard

3、)規(guī)定了一些子程序間調(diào)用的基本規(guī)則,這些規(guī)則包括子程序調(diào)用過程中寄存器的使用規(guī)則,數(shù)據(jù)棧的使用規(guī)則,參數(shù)的傳遞規(guī)則。有了這些規(guī)則之后,單獨編譯的C語言程序就可以和匯編程序相互調(diào)用。 使用ADS的C語言編譯器編譯的C語言子程序滿足用戶指定的ATPCS類型。而對于匯編語言來說,則需要用戶來保證各個子程序滿足ATPCS的要求。,2008年10月23日,7,AAPCS,2007年ARM公司正式推出了AAPCS標準 ARM Archtecture Procedure Call Standard AAPCS是ATPCS的改進版 目前, AAPCS和ATPCS都是可用的標準,2008年10月23日,8,寄存

4、器的使用規(guī)則,子程序間通過寄存器R0R3來傳遞參數(shù)。這時,寄存器R0R3可記作a0a3。被調(diào)用的子程序在返回前無需恢復(fù)寄存器R0R3的內(nèi)容。 在子程序中,使用寄存器R4R11來保存局部變量。這時,寄存器R4R11可以記作v1v8。如果在子程序中使用了寄存器v1v8中的某些寄存器,則子程序進入時必須保存這些寄存器的值,在返回前必須恢復(fù)這些寄存器的值。在Thumb程序中,通常只能使用寄存器R4R7來保存局部變量。 寄存器R12用作過程調(diào)用中間臨時寄存器,記作IP。在子程序之間的連接代碼段中常常有這種使用規(guī)則。,2008年10月23日,9,寄存器的使用規(guī)則(續(xù)),寄存器R13用作堆棧指針,記作SP。

5、在子程序中寄存器R13不能用作其他用途。寄存器SP在進入子程序時的值和退出子程序時的值必須相等。 寄存器R14稱為連接寄存器,記作LR。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14則可以用作其他用途。 寄存器R15是程序計數(shù)器,記作PC。它不能用作其它用途。,2008年10月23日,10,堆棧使用規(guī)則,ATPCS規(guī)定堆棧為FD類型,即滿遞減堆棧,并且對堆棧的操作是8字節(jié)對齊。 對于匯編程序來說,如果目標文件中包含了外部調(diào)用,則必須滿足下列條件: (1)外部接口的堆棧必須是8字節(jié)對齊的。 (2)在匯編程序中使用PRESERVE8偽指令告訴連接器,本匯編程序數(shù)據(jù)是8字節(jié)對

6、齊的。,2008年10月23日,11,參數(shù)傳遞規(guī)則,根據(jù)參數(shù)個數(shù)是否固定,可以將子程序分為參數(shù)個數(shù)固定的子程序和參數(shù)個數(shù)可變化的子程序。 這兩種子程序的參數(shù)傳遞規(guī)則是不一樣的。,2008年10月23日,12,參數(shù)個數(shù)可變子程序參數(shù)傳遞規(guī)則,對于參數(shù)個數(shù)可變的子程序,當參數(shù)個數(shù)不超過4個時,可以使用寄存器R0R3來傳遞參數(shù);當參數(shù)超過4個時,還可以使用堆棧來傳遞參數(shù)。 在傳遞參數(shù)時,將所有參數(shù)看作是存放在連續(xù)的內(nèi)存字單元的字數(shù)據(jù)。然后,依次將各字數(shù)據(jù)傳遞到寄存器R0,R1,R2和R3中。如果參數(shù)多于4個,則將剩余的字數(shù)據(jù)傳遞到堆棧中。入棧的順序與參數(shù)傳遞順序相反,即最后一個字數(shù)據(jù)先入棧。,200

7、8年10月23日,13,參數(shù)個數(shù)固定子程序參數(shù)傳遞規(guī)則,如果系統(tǒng)不包含浮點運算的硬件部件,浮點參數(shù)會通過相應(yīng)的規(guī)則轉(zhuǎn)換成整數(shù)參數(shù)(若沒有浮點參數(shù),此步省略),然后依次將各字數(shù)據(jù)傳送到寄存器R0R3中。如果參數(shù)多于4個,將剩余的字數(shù)據(jù)傳送堆棧中,入棧的順序與參數(shù)順序相反,即最后一個字數(shù)據(jù)先入棧。在參數(shù)傳遞時,將所有參數(shù)看作是存放在連續(xù)的內(nèi)存字單元的字數(shù)據(jù)。,2008年10月23日,14,子程序結(jié)果返回規(guī)則,子程序中結(jié)果返回的規(guī)則如下: 結(jié)果為一個32位整數(shù)時,可以通過寄存器R0返回; 結(jié)果為一個64位整數(shù)時,可以通過寄存器R0和Rl返回; 結(jié)果為一個浮點數(shù)時,可以通過浮點運算部件的寄存器f0、d

8、0或s0來返回; 結(jié)果為復(fù)合型浮點數(shù)(如復(fù)數(shù))時,可以通過寄存器f0fn或d0dn來返回; 對于位數(shù)更多的結(jié)果,需要通過內(nèi)存來傳遞。,2008年10月23日,15,5.7.2 ARM編譯器保有的特定關(guān)鍵字,ARM編譯器支持一些對ANSI C進行擴展的關(guān)鍵詞。這些關(guān)鍵詞用于聲明變量、聲明函數(shù)、對特定的數(shù)據(jù)類型進行一定的限制。,2008年10月23日,16,用于聲明函數(shù)的關(guān)鍵詞 (雙下劃線起頭),_asm,內(nèi)嵌匯編 _inline,內(nèi)聯(lián)展開 _irq,聲明IRQ或FIQ的ISR _pure,函數(shù)不修改該函數(shù)之外的數(shù)據(jù) _softfp,使用軟件的浮點連接件 _swi,軟中斷函數(shù) _swi_indir

9、ect,軟中斷函數(shù),2008年10月23日,17,用于聲明變量的關(guān)鍵詞,register 聲明一個變量,告訴編譯器盡量保存到寄存器中。 _int64 該關(guān)鍵詞是long long的同義詞。 _global_reg 將一個已經(jīng)聲明的變量分配到一個全局的整數(shù)寄存器中。,2008年10月23日,18,5.8 典型ARM匯編語言程序舉例,請參看本課程教材嵌入式系統(tǒng)基礎(chǔ)教程中第151頁開始的第5.2節(jié)。,2008年10月23日,19,5.8.1 條件執(zhí)行舉例,求a和b兩整數(shù)最大公約數(shù)的C程序 While a!=b) If(ab) a-=b; else b-=a; ,2008年10月23日,20,條件執(zhí)行

10、舉例(續(xù)),如果用ARM匯編子程序來實現(xiàn),就是求r1和r2兩個寄存器中的兩個整數(shù)的最大公約數(shù)。使用條件執(zhí)行指令表示只有以下4句代碼: gcd cmp r1, r2 ;cmp與subs功能類似但不存結(jié)果 subgt r1, r1, r2 ;如果r1r2執(zhí)行此指令 sublt r2, r2, r1 ;如果r1r2則轉(zhuǎn)gcd標號 注:函數(shù)結(jié)束時r1=r2,都可以用作返回值。,2008年10月23日,21,5.8.2 32位地址送入一個寄存器中,下面指令段中的load指令根據(jù)輸入?yún)?shù)決定調(diào)用那個函數(shù)。具體做法是將函數(shù)的絕對地址通過LDR指令存入在r4寄存器中,由于是32的絕對地址,LDR會被解釋成以下

11、操作:將函數(shù)的絕對地址放入一個文字池(Literal pool,嵌入在代碼中的用以存放常數(shù)的區(qū)域)。產(chǎn)生一條形如:LDR rn pc, #offset to literal pool的指令來將這個絕對地址讀入到指定的寄存器中。 類似地LDR指令也通過上述方法讀入一個32位的絕對數(shù)。在下例中,LDR指令將32位絕對數(shù)0 x11552634讀入到r0寄存器中,用作調(diào)用routine1或者routine2的參數(shù)。,2008年10月23日,22,32位地址送入一個寄存器中(續(xù)),;void load(int i) ;void routine1(int 1); ;void routine2(int 2)

12、; AREA LOAD, CODE, READONLY IMPORT routine1 IMPORT routine2 EXPORT load load stmfd r13!, r4, r14 ldr r4, = routine1 ;首先將32位地址存放在附近的區(qū)域 cmps r0, #1 ldrne r4, = routine2 ldr r0 = 0 x11552634 ;函數(shù)的第1個int參數(shù) bx r4 ldmfd r13!, r4, r14 bx r14,2008年10月23日,23,5.8.3 從IRQ和FIQ異常處理程序返回,從IRQ和FIQ異常處理程序返回時,返回地址應(yīng)該是LR-

13、4。 有三種不同的編程方法,分別列出如下: 返回方式1 INT_HANDLER SUBS PC, LR, #4 ; PC=R14-4,2008年10月23日,24,從IRQ和FIQ異常處理程序返回(2),返回方式2 INT_HANDLER SUB R14, R14, #4 ; R14 -=4 MOVS PC, LR,2008年10月23日,25,從IRQ和FIQ異常處理程序返回(3),返回方式3 INT_HANDLER SUB R14, R14, #4 ; R14 = R14 4 STMFD R13!, R0-R3, R14 LDMFD R13!, R0-R3, R15,2008年10月23日

14、,26,5.8.4 調(diào)用ARM匯編語言子程序,在ARM匯編語言中,子程序調(diào)用是通過BL指令完成的。BL指令的語法格式如下: BL subname 其中,subname是調(diào)用的子程序的名稱。 BL指令完成兩個操作:將子程序的返回地址放在LR寄存器中,同時將PC寄存器值設(shè)置成目標子程序的第一條指令地址。 在子程序返回時可以通過將LR寄存器的值傳送到PC寄存器中來實現(xiàn)。 子程序調(diào)用時通常使用寄存器R0R3來傳遞參數(shù)和返回結(jié)果。,2008年10月23日,27,調(diào)用匯編子程序舉例,子程序DOADD完成加法運算,操作數(shù)放在R0和R1寄存器中,結(jié)果放在R0中。 AREA EXAMPLE2, CODE, RE

15、ADONLY ENTRY start MOV r0, #10 ;R0設(shè)置輸入?yún)?shù) MOV r1, #3 ;R1設(shè)置輸入?yún)?shù) BL doadd ;調(diào)用子程序doadd doadd ADD r0, r0, r1 ;子程序?qū)嶓w MOV pc,lr ;從子程序中返回 END,2008年10月23日,28,5.8.5 循環(huán)結(jié)構(gòu),在ARM匯編中,沒有專門的指令用來實現(xiàn)循環(huán),一般通過跳轉(zhuǎn)指令加條件碼的形式來實現(xiàn)??梢圆捎帽容^指令CMP或者減法指令SUB等實現(xiàn)。參看下面的指令段: LOOP ADD R4, R4, R0 ADD R0, R0, #1 CMP R0, R1 BLE LOOP ; R0小于等于R1

16、場合跳轉(zhuǎn) 在做完了兩次加法操作后,比較R0,R1的值,影響條件標志。最后的條件跳轉(zhuǎn)語句根據(jù)CMP指令執(zhí)行的結(jié)果來決定是否進行循環(huán)。,2008年10月23日,29,5.8.6 數(shù)據(jù)塊復(fù)制示范程序,本程序?qū)?shù)據(jù)從源數(shù)據(jù)區(qū)復(fù)制到目標數(shù)據(jù)區(qū) 復(fù)制時,以8個字為單位進行。 對于最后所剩不足8個字的數(shù)據(jù),以字為單位進行復(fù)制,這時程序跳轉(zhuǎn)到copywords處執(zhí)行。 在進行以8個字為單位的數(shù)據(jù)復(fù)制時,保存了所用的8個工作寄存器。程序清單如下面所示。,2008年10月23日,30,數(shù)據(jù)塊復(fù)制示范程序(1),;設(shè)置本段程序的名稱(Block)及屬性 AREA Block, CODE, READONLY ;設(shè)置將

17、要復(fù)制的字數(shù) num EQU 20 ;標識程序入口點 ENTRY Start ;r0寄存器指向源數(shù)據(jù)區(qū)src LDR r0, =src ;r1寄存器指向目標數(shù)據(jù)區(qū)dst LDR r1, =dst,2008年10月23日,31,數(shù)據(jù)塊復(fù)制示范程序(2),;r2指定將要復(fù)制的字數(shù) MOV r2, #num ;設(shè)置數(shù)據(jù)棧指針(r13),用于保存工作寄存器數(shù)值 MOV sp, #0 x400 ;進行以8個字為單位的數(shù)據(jù)復(fù)制 blockcopy ;需要進行的以8個字為單位的復(fù)制次數(shù) MOVS r3,r2, LSR #3 ;對于剩下不足8個字的數(shù)據(jù),跳轉(zhuǎn)到copywords,以字為單位復(fù)制 BEQ cop

18、ywords ;保存工作寄存器,壓棧 STMFD sp!, r4r11,2008年10月23日,32,數(shù)據(jù)塊復(fù)制示范程序(3),octcopy ;從源數(shù)據(jù)區(qū)讀取8個字的數(shù)據(jù),放到8個寄存器中,并更新目標數(shù)據(jù)區(qū)指針r0 LDMIA r0!, r4-r11 ;將這8個字數(shù)據(jù)寫入到目標數(shù)據(jù)區(qū)中,并更新目標數(shù)據(jù)區(qū)指針r1 STMIA r1!, r4-r11 ;將塊復(fù)制次數(shù)減1 SUBS r3, r3, #1 ;循環(huán),直到完成以8個字為單位的塊復(fù)制 BNE octcopy ;恢復(fù)工作寄存器值,出棧 LDMFD sp!, r4-r11,2008年10月23日,33,數(shù)據(jù)塊復(fù)制示范程序(4),copywor

19、ds ;剩下不足8個字的數(shù)據(jù)的字數(shù) ANDS r2, r2, #7 ;數(shù)據(jù)復(fù)制完成 BEQ stop wordcopy ;從源數(shù)據(jù)區(qū)讀取1個字的數(shù)據(jù),放到r3寄存器中,并更新目標數(shù)據(jù)區(qū)指針r0,后索引偏移 LDR r3, r0, #4 ;將這r3中數(shù)據(jù)寫入到目標數(shù)據(jù)區(qū)中,并更新目標數(shù)據(jù)區(qū)指針r1,后索引偏移 STR r3, r1, #4,2008年10月23日,34,數(shù)據(jù)塊復(fù)制示范程序(5),;將字數(shù)減1 SUBS r2, r2, #l ;循環(huán),直到完成以字為單位的數(shù)據(jù)復(fù)制 BNE wordcopy ;定義數(shù)據(jù)區(qū)BlockData AREA BlockData, DATA, READWRITE

20、 ;定義源數(shù)據(jù)區(qū)src及目標數(shù)據(jù)區(qū)dst src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4 dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;結(jié)束匯編 END,2008年10月23日,35,5.8.7 內(nèi)嵌匯編,內(nèi)嵌匯編(inline assembly)的語法如下: _asm 指令;指令 /* 注釋 */ 指令 ,2008年10月23日,36,內(nèi)嵌匯編的指令用法,內(nèi)嵌在C或者C+程序中的ARM匯編指令與普通(ADS)格式的ARM匯編指令有所不同。其主要原因在于C/C+編譯器在編譯C/C+源代碼的同時要

21、兼顧處理內(nèi)嵌匯編程序,因此CPU的內(nèi)部寄存器資源使用有額外約束。以下講解內(nèi)嵌ARM匯編指令的用法。,2008年10月23日,37,ARM內(nèi)嵌匯編程序的操作數(shù),內(nèi)嵌匯編指令中作為操作數(shù)的寄存器和常量可以是表達式。這些表達式可以是char,short或int類型,而且這些表達式都是作為無符號數(shù)進行操作。若需要帶符號,用戶需要自己處理與符號有關(guān)的操作。編譯器將會計算這些表達式的值,并為其分配寄存器。,2008年10月23日,38,ARM內(nèi)嵌匯編程序的物理寄存器,內(nèi)嵌匯編程序中使用物理寄存器有以下限制。 不能直接向PC寄存器賦值,程序跳轉(zhuǎn)只能使用B或BL指令實現(xiàn) 不要使用過于復(fù)雜的C表達式,因為將會需

22、要較多的物理寄存器,這將導(dǎo)致與其他指令中用到的物理寄存器產(chǎn)生使用沖突。 編譯器可能會使用R12或R13存放編譯的中間結(jié)果,在計算表達式的值時可能會將寄存器R0R3,R12和R14用于子程序調(diào)用。因此在內(nèi)嵌的匯編指令中不要將這些寄存器同時指定為指令中的物理寄存器。 通常內(nèi)嵌的匯編指令中不要指定物理寄存器,因為這可能會影響編譯器分配寄存器,進而影響代碼的效率。,2008年10月23日,39,其他內(nèi)嵌匯編程序的編寫注意點,常量:在內(nèi)嵌匯編指令中,常量前面的“#”可以省略。 指令展開:內(nèi)嵌匯編指令中,如果包含常量操作數(shù),該指令可能被內(nèi)嵌匯編器展開成幾條指令。 標號:C程序中的標號可以被內(nèi)嵌的匯編指令使

23、用,但是只有指令B可以使用C程序中的標號,而指令BL則不能使用。 內(nèi)存單元的分配:所有的內(nèi)存分配均由C編譯器完成,分配的內(nèi)存單元通過變量供內(nèi)嵌匯編器使用。內(nèi)嵌匯編器不支持內(nèi)嵌程序中用于內(nèi)存分配的偽指令。,2008年10月23日,40,內(nèi)嵌匯編程序中的SWI和BL指令,SWI和BL指令:在兩個指令使用到內(nèi)嵌匯編中,除了正常的操作數(shù)域外,還必須增加以下3個可選的寄存器列表: 用于輸入?yún)?shù)的寄存器列表。 用于存儲返回結(jié)果的寄存器列表。 用于表示那些寄存器將有可能會被修改的寄存器列表。,2008年10月23日,41,內(nèi)嵌匯編代碼舉例字符串復(fù)制(1),#include void str_cpy(cons

24、t char *src,char *dst) int ch; _asm loop: /普通ARM匯編代碼中的標號后面不能跟冒號。C程序中 /的標號可以被內(nèi)嵌的匯編指令使用。 ARM內(nèi)嵌匯編代碼中 /只有B指令可以使用C的標號,而BL指令不能夠使用C代碼 /的標號。 C程序的標號后面跟冒號,由Goto語句轉(zhuǎn)向標號處。 LDRB ch, src, #1 STRB ch, dst, #1 CMP ch, #0 BNE loop ,2008年10月23日,42,內(nèi)嵌匯編代碼舉例字符串復(fù)制(2),int main(void) const char * a=Hello world!n; char b20;

25、 / do inline assembly routine str_cpy(a,b) _asm MOV R0,a / 將串a(chǎn)的串首地址送到R0寄存器 MOV R1,b / 將串b的串首地址送到R1寄存器 BL str_cpy, R0, R1 / 調(diào)用C函數(shù)str_cpy() printf(Original string: %sn,a); printf(Copied string: %sn,b); / 半主機方式顯示復(fù)制前后的兩個串 return(0); ,2008年10月23日,43,5.8.8 ARM匯編、C和C+混合編程,在C/C+程序中如果必須使用匯編指令來完成某些操作,可以采用兩種方法

26、:1.采用內(nèi)嵌匯編,即在C/C+源程序中嵌入一塊匯編代碼,讓這塊匯編代碼來完成特定的操作;2.將必須使用匯編代碼的部分獨立編寫成在一個文件中,形成一個子程序,C/C+程序可以調(diào)用這些匯編程序來完成特定的操作。,2008年10月23日,44,C/C+程序與ARM匯編語言程序的相互調(diào)用,C/C+程序與匯編程序相互調(diào)用時,應(yīng)遵守相應(yīng)的ATPCS,主要有五種調(diào)用。 ARM匯編子程序調(diào)用C語言子程序 ARM匯編子程序調(diào)用C+語言子程序 C語言程序調(diào)用ARM匯編語言子程序 C+語言程序調(diào)用ARM匯編語言子程序 C語言程序調(diào)用C+語言子程序 下面就每種具體情況逐一舉例說明。,2008年10月23日,45,C

27、/C+程序調(diào)用ARM匯編子程序要點,設(shè)計匯編程序必須遵守ATPCS,保證程序調(diào)用時參數(shù)的正確傳遞。 在匯編程序中使用EXPORT指示符聲明本程序可以被別的程序調(diào)用。 在C語言程序中使用extern關(guān)鍵詞聲明該匯編程序可以被調(diào)用,C+語言程序使用extern “C”來聲明該匯編程序可以被調(diào)用。,2008年10月23日,46,例1 C程序調(diào)用ARM匯編子程序,/* main_0522.c semihosting output mode */ #include extern int asmfile(int arg1, int arg2, int arg3); int main(void) int a

28、1=1,a2=2,a3=4; printf(Example of C Program calling Assembly program!n); printf(%d + %d + %d) * 600 = %dn,a1,a2,a3,asmfile( a1, a2, a3); ,2008年10月23日,47,C程序調(diào)用ARM匯編子程序(續(xù)),; ASM_0522.s EXPORT asmfile AREA My_pro, CODE, READONLY asmfile STMFD SP!, R4-R6,R8,R7 add r0, r0, r1 add r0, r0, r2 mov r4, #600 m

29、ul r3, r0, r4 mov r0, r3 LDMFD SP!, R4-R6,R8,R7 mov pc, lr END,2008年10月23日,48,例2 ARM匯編程序調(diào)用C語言子程序,本案例程序比較兩個IP地址的大小,a1a4存放IP地址1的值(按照ATPCS傳遞參數(shù)),b1b4存放IP地址2的值(通過棧傳遞參數(shù)),如果IP地址1的值大于IP地址2的值則返回1,如果IP地址1的值小于IP地址2的值則返回-1 ,如果兩者相等則返回零。 IP地址1取值:192, 168, 1, 152, IP地址2取值: 172, 0, 0, 151,2008年10月23日,49,例2 ARM匯編程序調(diào)

30、用C子程序(續(xù)),/* C代碼部分 */ #include extern int function(void); /* 聲明function是外部函數(shù) */ int compare_ip(int a1, int a2, int a3, int a4, int b1, int b2, int b3, int b4) if(a1!=b1) return a1b1?1:-1; if(a2!=b2) return a2b2?1:-1; if(a3!=b3) return a3b3?1:-1; if(a4!=b4) return a4b4?1:-1; return 0; int main() print

31、f(This is a example of semihostingn); printf(result is %dn,function(); ,2008年10月23日,50,例2 ARM匯編調(diào)用C子程序(續(xù)2),AREA FUNCTION, CODE, READONLY ;ARM匯編子程序 IMPORT compare_ip EXPORT function function STMFD r13!,r0-r3,r14 ;保存寄存器到棧區(qū) MOV r3,#0 x97 ;存入IP地址2的4個數(shù), 0 x97=151 MOV r2,#0 ; 存入0 MOV r1,#0 ; 存入0 MOV r0,#0

32、xac ; 存入0 xac=172 STMIA r13, r0-r3 ; R0-R4覆蓋存入棧區(qū)的R0-R4位置 MOV r3,#0 x98 ; 存入IP地址1的4個數(shù), 0 x98=152 MOV r2,#1 ; 存入1 MOV r1,#0 xa8 ; 存入0 xa8=168 MOV r0,#0 xc0 ; 存入0 xc0=192 BL compare_ip ; 0 x0 ; 調(diào)用C語言函數(shù)進行IP值比較 ADD r13,r13,#0 x10 ; 棧指針上移4個字(元素) LDR pc,r13,#4 ; 將保存的r14值加載到PC,而后r13加4 END ; 本段匯編代碼的操作圖解參看下一頁

33、,2008年10月23日,51,例2 ARM匯編調(diào)用C子程序(續(xù)3),ARM匯編語言子程序Function的棧區(qū)操作圖解,2008年10月23日,52,例3 ARM匯編程序調(diào)用 C+子程序,/ 這是C+調(diào)用ARM匯編的范例程序 / 文件名:try_C+_call_S / main函數(shù)位于這個.CPP文件 extern C void asmfunc(void); int main(void) asmfunc(); ,2008年10月23日,53,例3 ARM匯編調(diào)用 C+子程序(續(xù)),; 這個ARM匯編語言程序被main函數(shù)調(diào)用 ; 該函數(shù)又調(diào)用ARM匯編函數(shù)cppfunc ; AREA myp

34、ro, CODE, READONLY IMPORT cppfunc EXPORT asmfunc asmfunc STMFD sp!,lr BL cppfunc LDMFD sp!,pc END,2008年10月23日,54,例3 ARM匯編調(diào)用 C+子程序(續(xù)2),#include #include using namespace std; const double PI = 3.1415926; class point public: point()x=0; y=0; point(double a, double b) x=a; y=b; point(point ,2008年10月23日,

35、55,例3 ARM匯編調(diào)用 C+子程序(續(xù)3),double GetX() return x; double GetY() return y; point ,2008年10月23日,56,例3 ARM匯編調(diào)用 C+子程序(續(xù)4),this-x = length * cos(a+degree*PI/180); this-y = length * sin(a+degree*PI/180); return *this; ; private: double x, y; ;,2008年10月23日,57,例3 ARM匯編調(diào)用 C+子程序(續(xù)5),extern C int cppfunc() point

36、a(1.5, 1.9); point b(2.0, 0.0); point c(1.0, 1.0); a.Move(b); c.Rotate(90); couta is (a.GetX(),a.GetY()endl; coutb is (b.GetX(),b.GetY()endl; coutc is (c.GetX(),c.GetY()endl; couta and b s retangle area is a.GetArea(b)endl; coutb and c s retangle area is b.GetArea(c)endl; couta and c s retangle area

37、 is a.GetArea(c)ca cppfunc(s); /* 調(diào)用C+函數(shù)cppfunc(),初始化 s */ ,2008年10月23日,60,例4 C語言程序調(diào)用 C+子程序(續(xù)1),int main() struct S s; f( ,2008年10月23日,61,例4 C語言程序調(diào)用 C+子程序(續(xù)2),/ CPP.CPP函數(shù)清單 class S / has no base classes or virtual functions public: char ca12; S() ca0=0; ; extern C void cppfunc(S *p) / Definition of

38、the C+ function to be called from C. / The function is written in C+, only the linkage is C char * tmp=world!; char * source=p-ca; while(*source !=0) /掃描過原先在c程序中的賦值 source+; *source+ = ; /將結(jié)束符改為空格 while(*source+ = *tmp+); /copy world to p-ca ,2008年10月23日,62,ARM匯編(子)程序的相互調(diào)用,基本要點: 如果一個ARM匯編語言程序文件含有調(diào)用外

39、部匯編語言程序文件中子程序(函數(shù))的指令,則需要用IMPORT指示符來指明將要調(diào)用的子程序名稱。 如果本匯編語言程序文件中的某個子程序(函數(shù)),需要被外部的ARM匯編語言程序文件中的語句調(diào)用,則需要用EXPORT指示符來指明將要被調(diào)用的子程序(函數(shù))名稱。 被執(zhí)行的匯編子程序在運行前,要注意將寄存器組壓入棧區(qū),返回時要注意將棧區(qū)保存的工作現(xiàn)場恢復(fù)到處理器的寄存器組。,2008年10月23日,63,例5 ARM匯編子程序嵌套調(diào)用舉例-1,這里給出的ARM匯編程序嵌套調(diào)用范例程序做如下計算: 求自然數(shù)1到n的階乘的總和,半主機方式輸出 運算結(jié)果如下圖所示。第3行顯示的是19的階乘,第2行顯示的是1

40、!+2!+3!+4!+5!+6!+7!+8!+9!之總和。,2008年10月23日,64,例5 ARM匯編子程序嵌套調(diào)用舉例-2,/* This program is semihosting output mode */ /* First the main function call assembly summing subprogram */ /* Then the summing subprogram call assembly factorial subprogram */ #include extern int asmFac(int n); struct factorial_sum i

41、nt cal_fn; int sum_fn; int fn9; ; extern struct factorial_sum * summing(struct factorial_sum * arg1);,2008年10月23日,65,例5 ARM匯編子程序嵌套調(diào)用舉例-3,int main(void) int j; struct factorial_sum fac= 9, 0, 1,1,1,1,1,1,1,1,1 ; /設(shè)置參數(shù) struct factorial_sum * result; /申請變量作為返回值 printf(Example of a multi Assembly progra

42、m calling !n); result=summing( ,2008年10月23日,66,例5 ARM匯編子程序嵌套調(diào)用舉例-4,;the details of parameters transfer comes from ATPCS ;if there are more than 4 args, stack will be used EXPORT summing IMPORT asmFac ;說明用到了其他文件中的子匯編程序 AREA SUMMING, CODE, READONLY summing STMFD SP!, R4-R5 ldr r1, r0 ;r1=cal_fn mov r2

43、, #1 ;將r2設(shè)置為當前需要計算的階乘數(shù), ;它從1變化到cal_fn add r3, r0, #8 ;將r3指向fn數(shù)組 mov r5, #0 ;r5為總和,初始值置為0 loop cmp r1, r2 ;將cal_fn與當前所需計算的階乘值比較 blt back ;如果小于,則返回,2008年10月23日,67,例5 ARM匯編子程序嵌套調(diào)用舉例-5,STMFD SP!, R0-R3,lr ;保存ror3,lr ;因為調(diào)用了外部文件的匯編子程序 mov r0, r2 ;將r0設(shè)置為當前所需計算的階乘值 bl asmFac ;調(diào)用階乘函數(shù) mov r4, r0 ;將返回值(階乘)存在r4

44、中 ldmfd SP!, R0-R3,lr ;恢復(fù)先前保存的寄存器值 str r4, r3 ;將計算所得的階乘值存入數(shù)組中 add r3, r3, #4 ;將r3指向數(shù)組的下一個 add r5, r5, r4 ;將階乘值加入總和 add r2, r2, #1 ;計算下一個階乘 b loop ;循環(huán) back str r5, r0, #4 ;將計算所得的總和存入結(jié)構(gòu)體中 ldnfd SP!, R4-R5 ;恢復(fù)寄存器值 mov pc, lr ; summing子程序返回 END ;匯編代碼結(jié)束,2008年10月23日,68,例5 ARM匯編子程序嵌套調(diào)用舉例-6,;the details of

45、parameters transfer comes from ATPCS ;if there are more than 4 args, stack will be used ;這個ARM匯編函數(shù)也可以被C函數(shù)調(diào)用,符合ATPCS規(guī)范 ;int asmFac(int n) EXPORT asmFac AREA ASMFILE, CODE, READONLY asmFac mov r1, r0 ;r1=n loop subs r1, r1, #1 ;將r1減1 mulgt r0, r1, r0 ;如果大于0,則乘上r1(相當與n*(n-1) bgt loop ;如果大于0,繼續(xù) mov pc,

46、lr ;asmFac子程序返回 END ;匯編代碼結(jié)束,2008年10月23日,69,ARM9五級流水線互鎖現(xiàn)象舉例,互鎖使得指令的執(zhí)行周期增加,下面舉例說明: LDR r1, r2,#8 ADD r0, r0, r1 MOV r2, #0,2008年10月23日,70,5.8.9 5級流水線的互鎖問題,ARM9指令流水線有5級。 五個流水線階段分別是:取指、譯碼、ALU、LS1、LS2。 流水線的增加增加了系統(tǒng)的吞吐量,但也引起了流水線互鎖(pipeline interlock),即一條指令需要前一條指令的執(zhí)行結(jié)果,而這時結(jié)果還沒有出來,那么處理器就會等待。,2008年10月23日,71,A

47、RM9五級流水線互鎖現(xiàn)象的圖解,2008年10月23日,72,ARM9五級流水線互鎖現(xiàn)象的解決,如果將指令順序該為: LDR r1, r2,#8 MOV r2, #0 ADD r0, r0, r1 這樣的指令順序執(zhí)行由于沒有產(chǎn)生流水線互鎖,執(zhí)行上述指令只需要3個周期,即一個時鐘周期完成一條指令。在保持結(jié)果正確無誤的前提下,比修改之前減少了一個時鐘周期。,2008年10月23日,73,5.8.10 ARM匯編語言程序中的宏定義和宏指令,指示符MACRO和MEND MACRO指示符標識宏定義的開始,MEND標識宏定義的結(jié)束。 用MACRO及MEND定義一段代碼,稱為宏定義體,這樣在程序中就可以通過宏指令多次調(diào)用該代碼段。,2008年10月23日,74,MACRO和MEND指示符,語法: MACRO $label macroname $paprameter, $papramet

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論