【環(huán)球快播報】嵌入式:ARM匯編語言程序設計基礎教程

2022-12-30 11:26:16 來源:51CTO博客

匯編語言程序設計的步驟

① 合理地分配存儲器資源,將前述的目標系統(tǒng)‘數(shù)據結構模型’表示到各存儲器單元。


(相關資料圖)

② CPU寄存器數(shù)量有限,在程序中,大多數(shù)操作都要使用寄存器;并且有的操作使用特定的寄存器(如堆棧操作使用SP/R13等),程序中要合理分配各寄存器的用途。

用計算機語言,對數(shù)據結構模型和流程圖表示的算法進行準確地描述。

① 語法調試:排除程序中的語法錯誤。

② 功能調試:保證程序的邏輯功能正確性。

用文檔形式記錄說明程序的功能、使用方法、程序結構、算法流程等每一個階段的工作。 把解題的方法、步驟用框圖形式表示。如果問題比較復雜,那么可以逐步細化,直到每一框圖可以容易編程為止。流程圖不僅便于程序的編制,且對程序邏輯正確性也比較容易查找和修改。

順序程序設計

順序程序是一種最簡單的程序結構,也稱為直線程序,它的執(zhí)行自始自終按照語句的先后順序進行。這種結構的流程圖,除了有一個起始框,一個終止框外,就是若干執(zhí)行框。

例:試編制一程序,完成10+3的操作。

AREA  ARMex, CODE, READONLY ; 代碼段名ARMexENTRY         ; 程序的入口CODE 32start  MOV R0, #10   ; 將立即數(shù)10存入寄存器R0  MOV R1, #3    ; 將立即數(shù)3存入寄存器R1  ADD R0, R0, R1  ; R0 = R0 + R1stop  MOV R0, #0x18   ; 這三條指令是ADS調試環(huán)境特約  LDR R1, =0x20026  ;程序運行結束返回編譯器調試環(huán)境  SWI   0x123456END       ; 結束

分支程序設計

許多實際問題需要根據不同的情況作出不同的處理。在程序中,針對不同的情況把不同的處理方法編制成各自的處理程序段,運行時由機器根據當時的條件自動作出判斷,選擇執(zhí)行相應的處理程序段。這樣的程序結構中,計算機不再完全按指令存儲的順序執(zhí)行,稱之為分支。分支程序使用轉移指令B、子程序調用指令BL或帶狀態(tài)轉移指令BX來實現(xiàn)。

例:給定以下符號函數(shù):

任意給定值,假定為-25,存放在x單元,函數(shù)值存放在y單元;要求根據x中的值來確定y的值。

AREA symbol, CODE, READONLY ; 代碼段的名字 symbol ENTRY           ; 程序的入口 CODE32start LDR   R0, =x ; 加載數(shù)據段中的變量x地址,存入R0 LDR   R1, =y ; 加載數(shù)據段中的變量y地址,存入R1 LDR R2, [R0] ; 加載變量x的值,存入R2compare CMP R2, #0 ; 將R2的值與0作比較 BEQ ZERO ; 如果R2等于0,那么轉向標號ZERO處 BGT PLUS ; 如果R2大于0,那么轉向標號PLUS處 MOV R3, #-1 ; 否則,R2小于0,將-1存入R3中 B stopZERO MOV R3, #0 ; R2等于0,將0存入R3中 B stopPLUS MOV R3, #1 ; R2大于0,將1存入R3中; 續(xù)上段代碼stop   STR R3,  [R1] MOV R0,  #0x18  LDR R1, =0x20026 SWI 0x123456      AREA Data, DATA, READWRITEx DCD -25y DCD 0   END

循環(huán)程序設計

順序程序和分支程序中的指令每次運行最多只執(zhí)行一次。在實際應用中重復地做某些事的情況很多,這也是計算機最擅長的工作方式。重復地執(zhí)行某些指令,最好用循環(huán)程序來實現(xiàn)。循環(huán)程序的結構---重復地執(zhí)行同一種運算,直到某種條件滿足。

建立循環(huán)初始值。如設置地址指針、計數(shù)器、其他循環(huán)參數(shù)的起始值等。循環(huán)程序的主體業(yè)務代碼,可以是一個順序程序、分支程序或另一個循環(huán)程序。 為執(zhí)行下一個循環(huán)而修改某些參數(shù),尤其循環(huán)控制變量的修改等。

條件控制循環(huán):通過判斷循環(huán)終止條件是否已成立,控制循環(huán)。判斷循環(huán)結束條件是否成立,決定是否繼續(xù)循環(huán)。

例如:計數(shù)控制循環(huán);通過計數(shù)循環(huán)次數(shù),判斷是否已達到預定次數(shù),控制循環(huán)。對循環(huán)結束進行適當處理;有的循環(huán)程序可以沒有這部分。

用計數(shù)控制循環(huán)適用于已知循環(huán)次數(shù)的循環(huán)程序設計

例:從x單元開始的30個連續(xù)字單元中存放有30個無符號數(shù),從中找出最大者送入y單元中。

分析:

根據題意,把第一個數(shù)先送入Rx寄存器,將Rx中的數(shù)與后面的29個數(shù)逐個進行比較,如果Rx中的數(shù)較小,則將該較大的數(shù)送入Rx ;繼續(xù)與余下的數(shù)據逐個比較。在比較過程中, Rx中始終保持較大的數(shù),共計比較29次,則最終Rx中保留了最大數(shù),最后把Rx中的數(shù)(最大者)送入y單元。

AREA  max, CODE, READONLY   ; 代碼段的名字 max  ENTRY                         ; 程序的入口  CODE32num EQU 29                   ; 比較的次數(shù)start  LDR R0,  =x           ; R0指向源數(shù)據塊x  LDR R1,  =y           ; R1指向單元y  LDR R2,  =num      ; R2作為計數(shù)器  LDR R3,  [R0]        ; 將源數(shù)據塊x中第一個數(shù)加載到R3中compare  ADD R0, R0, #4       ; 每進行一次比較,將R0指針地址加4  LDR R4, [R0]          ; 依次將源數(shù)據塊x中下一個數(shù)加載到R4中  CMP R3, R4             ; 比較R3和R4中數(shù)的大小   MOVCC  R3,  R4          ; 如果R3小于R4,則將較大的數(shù)送入R3中  SUBS  R2,  R2,  #1       ; 計數(shù)器值減1  BNE compare           ; 如果不為0,那么繼續(xù)跳到compare執(zhí)行  STREQ R3,  [R1]          ; 如果為0,那么循環(huán)比較結束,R3是最大的數(shù)             ; 并且將R3中的數(shù)加載到R1指向的單元(即y)中 stop  MOV r0, #0x18  LDR r1, =0x20026      SWI 0x123456          AREA  Data, DATA, READWRITEx DCD 73,59,61,34,81,107,225,231,54,43  DCD 100,35,1,42,222,254,34,71,100,31  DCD 33,119,13,44,18,147,55,244,97,3y DCD 0  END

② 適用于已知循環(huán)條件的循環(huán)程序設計

適用于無法確定循環(huán)次數(shù),但知道循環(huán)結束的條件

例:從自然數(shù)1開始累加,直到累加和大于1000為止,統(tǒng)計被累加的自然數(shù)的個數(shù),并把統(tǒng)計的個數(shù)送入n單元,把累加和送入sum單元。

分析:

根據題意,被累加的自然數(shù)的個數(shù)事先未知,因此不能用計數(shù)方法控制循環(huán)。但題目中給定一個條件,即累加和大于1000則停止累加,因此,可以根據這一條件控制循環(huán)。我們用R3寄存器放累加和,用R4寄存器放每次取得的自然數(shù),其中它的值也是統(tǒng)計自然數(shù)的個數(shù)。

AREA  SUM, CODE, READONLY ; 代碼段的名字 SUM     ENTRY                        ; 程序的入口     CODE32start     LDR   R0,   =n            ; 將數(shù)據段中自然數(shù)的個數(shù)n的地址加載到R0寄存器     LDR   R1,   =sum       ; 將數(shù)據段中自然數(shù)的累加和sum的地址加載到R1寄存器     LDR   R3,   =0            ; R3存放自然數(shù)的累加和     LDR   R4,   =0            ; R4用于循環(huán)個數(shù)的統(tǒng)計/每次取得的自然數(shù)     LDR   R5,   =1000      ; R5用于循環(huán)結束的界限值continue     ADD  R4,   R4,     #1    ; 取下一個自然數(shù)     ADD  R3,   R3,    R4    ; 累加自然數(shù)     CMP  R3,   R5             ; 比較累加和是否超過了1000     BCC  continue            ; 如果小于1000,那么跳到compare執(zhí)行     STRCS   R3,  [R1]     ; 如果大于1000,那么將累加和存儲到R1所指向的單元中     STRCS   R4,   [R0]    ; 如果大于1000,那么將已累加的自然數(shù)個數(shù)值存儲                ; 到R0所指向的單元中 stop        MOV    r0, #0x18        LDR     r1, =0x20026              SWI     0x123456                 AREA  Data, DATA, READWRITEn DCD 0     ; 定義累加的自然數(shù)的個數(shù)sum DCD 0      ; 定義自然數(shù)的累加和        END

子程序設計

子程序概念

如果在一個程序中的多處用到同一段程序代碼,那么可以把這段共同的程序代碼抽取出來,寫成一個相對獨立的程序段,每當需要執(zhí)行這段代碼時,就調用這個程序段,執(zhí)行完這個程序段后,再返回原來調用它的程序。這樣編寫程序時,就不必重復寫這段代碼了,而這樣的程序段稱為子程序或子過程。

子程序的調用與返回

主程序中使用BL指令實現(xiàn)子程序的調用

BL子程序名

在子程序結束處,使用如下指令返回到主程序中。

MOV PC, LR

主程序與子程序之間的參數(shù)傳遞

主程序調用子程序時,可以向子程序傳遞一些參數(shù);同樣,子程序運行后也可把一些結果參數(shù)傳回給主程序。主程序與子程序之間的這種信息傳遞稱為參數(shù)傳遞。

三種參數(shù)傳遞方式

寄存器傳遞參數(shù)方式存儲區(qū)域傳遞參數(shù)方式堆棧傳遞參數(shù)方式

寄存器傳遞參數(shù)方式

例:用子程序實現(xiàn)內存區(qū)里的字符串拷貝功能,即將存儲單元中源字符串對應拷貝到目的字符串中。

技術思想:主程序將待傳遞的數(shù)據直接寫入約定的通用寄存器,在子程序中直接使用;或子程序返回后,主程序直接從約定的通用寄存器中獲得子程序的結果數(shù)據。

應用特點:這種方式適合于傳遞較少參數(shù)的應用場合。

解題思路:

通過設定兩個地址指針,分別指向存儲區(qū)中的源字符串和目的字符串;然后通過加載和存儲指令(LDR和STR)的寄存器間接尋址方式,依次從源字符串讀取一個字符數(shù)據,寫入到目的字符串的對應字符位置中,直到遇到源字符串的結束標志’\0’為止。

AREA    StrCopy, CODE, READONLY        ENTRY        CODE32start        LDR       R1,    =srcstr        ; R1指向數(shù)據區(qū)的源字符串        LDR       R0,    =dststr        ; R0指向數(shù)據區(qū)的目的字符串        BL          strcopy                 ; 調用子程序strcopy,完成字符串拷貝stop        MOV     R0,     #0x18          ; 程序結束返回編譯器調試環(huán)境        LDR      R1,     =0x20026        SWI        0x123456strcopy         LDRB     R2,     [R1],    #1    ; 將R1指向的單元內容加載到R2中        STRB      R2,     [R0],    #1    ; 將R2中的數(shù)存儲到R0指向的單元中        CMP       R2,    #0                 ; 檢查R0的值是否等于0        BNE        strcopy                  ; 如果不等于0,那么轉到strcopy處執(zhí)行         MOV       PC,    LR               ; 子程序返回         AREA    Strings, DATA, READWRITEsrcstr  DCB "First string - source",0   ; 源字符串dststr  DCB "Second string - destination",0 ; 目的字符串        END

存儲區(qū)域傳遞參數(shù)方式

例:通過設置的入口參數(shù)查找函數(shù)地址表,實現(xiàn)選擇不同的函數(shù)功能。

說明:本題中通過事先將函數(shù)地址存放在存儲單元中,通過查找地址表的方法,實現(xiàn)根據“選擇項(choice)”進入不同的函數(shù)體功能。

技術思想:主程序和子程序約定了某一共享內存塊用于參數(shù)傳遞,主程序在BL調用子程序前,先將要傳遞的參數(shù)寫入到約定的存儲單元,子程序可從約定的內存讀取這些參數(shù);子程序返回時,也可以使用該方式將數(shù)據傳給主程序。

應用特點:這種方式可以傳遞大批量數(shù)據。

實現(xiàn)方法:當主程序與子程序有較多的數(shù)據需要傳遞時,可以通過共享內存區(qū)或傳內存數(shù)據塊地址方式來傳遞批量數(shù)據。

通過偽指令ADR直接裝載近距離數(shù)據塊地址;

通過偽指令ADRL直接裝載中距離數(shù)據塊地址;

通過語句LDR Rd, =Label轉載遠距離的數(shù)據塊地址;

AREA    Jump, CODE, READONLY       num     EQU     4      ; 函數(shù)地址表內容的個數(shù)       ENTRY       CODE32start     LDR   R0,   =choice    ; R0指向存儲區(qū)的choice單元       LDR   R0,   [R0]   ; 設置第一個參數(shù):選擇執(zhí)行哪一個函數(shù)       MOV  R1,   #16   ; 設置第1個操作數(shù)       MOV  R2,   #2    ; 設置第2個操作數(shù)       BL       arithfunc   ; 調用子程序arithfuncstop       MOV   R0,   #0x18    ; 程序結束返回編譯器調試環(huán)境       LDR    R1,   =0x20026       SWI       0x123456arithfunc       CMP   R0,    #num                     ; 比較R0的值是否超過函數(shù)地址表的個數(shù)       MOVHS   PC, LR     ; 如果大于,那么就返回到標號stop處       ADR   R3,    JumpTable ; 將函數(shù)地址表的地址作為基地址       LDR    PC,   [R3, R0, LSL #2]  ; 根據R0參數(shù)進入對應的子程序JumpTable ; 函數(shù)地址表的入口基地址        DCD       DoAdd   ; 加法子程序        DCD DoSub   ; 減法子程序        DCD DoMul   ; 乘法子程序        DCD DoDiv   ; 除法子程序DoAdd        ADD   R0,   R1,    R2               ; R0 = R1 + R2        MOV   PC,   LR    ; 返回DoSub        SUB    R0,  R1,    R2       ; R0 = R1 - R2        MOV   PC, LR    ; 返回DoMul         MOV   R0,   R1,  LSL R2   ; R0 = R1 << R2        MOV   PC,   LR    ; 返回DoDiv         MOV   R0,   R1,  LSR R2       ; R0 = R1 >> R2        MOV   PC,   LR    ; 返回        AREA  NUM, DATA, READWRITEchoice  DCD 3           ; 0:表示選擇加法子程序   1:表示選擇減法子程序                 ; 2:表示選擇乘法子程序   3:表示選擇除法子程序        END

堆棧傳遞參數(shù)方式

主程序和子程序使用同一個堆棧,主程序在BL調用子程序前,先將要傳遞的參數(shù)壓入到堆棧中,子程序可從堆棧中讀取傳過來的數(shù)據;子程序返回需要向主程序傳遞參數(shù)時,也可使用此方法。

參考文獻:

孟祥蓮.嵌入式系統(tǒng)原理及應用教程(第2版)[M].北京:清華大學出版社,2017.

標簽: 程序設計 調用子程序 子程序返回

上一篇:環(huán)球動態(tài):shell 修改系統(tǒng)cpu使用率
下一篇:世界快報:Qt實現(xiàn)俄羅斯方塊