1樓:匿名使用者
arm彙編程式特點:
l 所有運算處理都是發生通用暫存器(一般是r0~r14)的之中.所有儲存器空間(如c語言變數的本質就是一個儲存器空間上的幾個byte).的值的處理,都是要傳送到通用暫存器來完成.
因此**中大量看到ldr,str指令來傳送值.
l arm彙編語句中.當前語句很多時候要隱含的使用上一句的執行結果.而且上一句的執行結果,是放在cpsr暫存器裡,(比如說進位,為0,為負…)
cmp r0,r1
bne nomatch
比如上一句,bne隱含的使用的上一句cmp執行結果.ne字尾表示使用z標誌位.兩句合起來的意思就是,如果r0,r1的值不相等,就跳轉到nomatch處執行.
注意,pc=r15,cpsr=r16,
arm偽指令不是必須的,但是一個完整沒有偽指令幾乎很難寫出來.
n 比如一個程式至少包含readonly area和entry,否則cpu都無法知道從**開始執行
l arm的屬於risc,指令並不多,但是可以帶字尾表示擴充套件出不同用法,這裡與x86彙編完全不同風格
n 如bne實際上是b指令的變種,本質還同一類指令.只是多一個對cpsr的z標誌位的判斷。
arm常用指令,偽指令
arm常用指令並不太多,因此使用閱讀arm彙編**,並不太困難.以下是使用頻率最高的指令和偽指令,並不是完整的指令集的教材。詳細指令參見參考資料。
l b,bl
l mov,mvn
l ldr,str
l add,sub,adc,sbc,mul
l and,orr,xor,tst,bic
l cmp
l ldm/stm
l nop
1. 跳轉語句 b,bl
程式流程的跳轉,在 arm 程式中有兩種方法可以實現程式流程的跳轉指令用於實現
l 使用專門的跳轉指令 b
l 直接向程式計數器pc 寫入跳轉地址值
n 這是幾乎是任何一種cpu必備的機器,pc表示cpu當前執行語句位置,改變pc的值,相當於實現程式跳轉
n 如實現類似c語言的return 語句,就是用mov pc,lr
n 這裡可以在任意4g的空間進行跳轉
b指令(branch)表示無條件跳轉.
b main ;跳轉到標號為main地**處
bl指令(branch with link)表示帶返回值的跳轉.
bl比b多做一步,在跳轉前,bl會把當前位置儲存在r14(即lr暫存器),當跳轉**結束後,用mov pc,lr指令跳回來,這實際上就是c語言執行函式的用法,
彙編裡調子程式都用bl,執行完子函式後,可以用mov pc,lr跳回來.
bl delay ;執行子函式或**段delay ,delay可以為c函式.
與mov pc,***能在4g空間跳轉不同,b語句只能32m空間跳轉,(因為偏移量是一個有符號26bit的數值=32m)
2. 傳輸資料指令mov,mvn
n mov(move)指令可完成從另一個暫存器、被移位的暫存器或將一個立即數載入到目的暫存器
mov r0,r1 ; 把r1的值傳到r0
mov r3,#3 ;把常數3傳給r3,mov中用#表示常數,這個值不能超過
n mvn( move negative)取反後再傳值,比mov多了一步取反
mvn r0, #0 ;把0取反(即-1)傳給r0
mvn r1,r2 ;把r2的值取反傳給r1
3. 載入/儲存指令,ldr,str
n ldr,str是用於暫存器和外部儲存器交換資料指令,注意與mov的區別,後面只在暫存器或常數交換.
u ldr/str可以採用多種定址方式,以下只舉出使用頻率最高几種用法
n ldr(load)用於把一個32bit的word資料從外部儲存空間裝入到暫存器中
ldr r0,[r1]; r1的值當成地址,再從這個地址裝入資料到r0 (r0=*r1)
ldr r1,=0x30008000 ; 把地址0x30008000的值裝入到r1中,ldr中用常數要用=打頭.(注意跟mov的區別,mov是#)
ldr r0, =(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)
用位與的方法賦值
n str(store) 用於把一個暫存器的值存入外部儲存空間,是ldr的逆操作.
str r0,[r1] ; 把r0的值,存入到r1對應地址空間上(*r1 = r0)
str r0,=0x30008000 ;把r0中值存入到地址0x30008000
s2c2440的中cpu核心以外的模組的控制暫存器空間也是屬於外部空間,所以也得用如下指令ldr r0,=gpfdat
4. 算術運算指令,add/adc,sub/sbc ,mul
n add加法指令
add r0,r1,r2; r0=r1+r2
add r0,r1,#3 ;r0=r1+3
n adc帶進位加法指令,即除了加兩個數以外,還要把cpsr的c值也要帶進來
u 通常用於大數(超過32bit整數)相加,這時單用add不能處理,必須折成兩步,其中一步用adc.
u 以下是做64bit的加法
adds r0,r1,r2; r0=r1+r2,adds中s表示把進位結果寫入cpsr
adc r5,r3,r4 ;r5=r3+r4+c
n sub減法指令
sub r0,r1,r2; r0=r1-r2
sub r0,r1,#3 ;r0=r1-3
n sbc帶進位減法指令,即除了加兩個數以外,還要把cpsr的c值也要帶進來,類似adc
u 以下是做64bit的減法
subs r0,r1,r2; r0=r1-r2,subs中s表示把進位結果寫入cpsr
sbc r5,r3,r4 ;r5=r3-r4-c
n mul 乘法指令
mul r0,r1,r2; r0=r1*r2
mul r0,r1,#3 ;r0=r1*3
5. 位操作指令 and,orr, tst,bic
n and位與指令
and r0,r1,r2; r0=r1 & r2
and r0,r1,#0xff ;r0=r1 & 0xff
n orr位或指令
orr r0,r1,r2; r0=r1 | r2
orr r0,r1,#0xff ;r0=r1 | 0xff
n tst測試某一位是否為1,並把結果寫入cpsr,供下一句使用
tst r1,#0xffe; 等同於if(r1 & 0xffe)
tst r1,#%1;測試最低位是否為1,%表示二進位制
n bic清位操作
bic r0,r0,#0xf ; 等同於 r0 &=~(0xf)
bic r0,r0,#%1011 ; 該指令清除 r0 中的位 0 1 3,其餘的位保持; %表示是二進位制,0x表示十六進位制
6. 比較指令 cmp
n cmp比較兩個運算元,並把結果存入cpsr供下一句語句使用
cmp r0,r1; 比較r0,r1
7. 多暫存器語句傳輸指令,ldm,stm
類似於一次傳一個buffer到暫存器當中,或反過來.後面一般要接一個地址改變方法
n ldm 從buffer傳資料多個暫存器傳輸資料到
ldmia r0! , ;加r0指向的地址上連續空間的資料,儲存到r3-r9當中,!表示r0值更新,ia字尾表示按word遞增
ldmfd sp!,^;恢復現場,異常處理返回,^表示不允許在使用者模式下使用。
n stm 從暫存器列表向儲存空間傳值。
stmia r1!, ;將r3-r9的資料儲存到r1指向的地址上,r1值更新。
stmfd sp!,; 現場儲存,將r0~r7,lr入棧
stmfd sp!, ,把sp暫存器對慶的地址的值存到r8,r9當中.!表示最後的值寫入sp中。fd表示
8. arm指令的變形
大部分指令後位可以接 與s兩個特殊位來表示,對cpsr特殊的一些判斷
s,表示當前指令執行後把結果改寫cpsr
subs,adds
取決於具體條件,只有cpsr滿足指定條件時才指這一指令
beq 實際上b+ eq的條件執行.
addne 表示add +ne 才開始加.
9. arm指令的定址方式
定址方式是根據指令中給出的地址碼來定位真實的地址,arm中有9種定址方法
l 暫存器定址
直接用暫存器編號來定址,最為常用
mov r1,r2 ;r2->r1
l 立即數定址
即指令中的地址碼是運算元本身,可以立即取出使用,立即數前帶一個#表示,否則表示一個地址
subs r0,r0,#1 ;r0 -1 ->r0
注意與subs r0,r0,1區別
l 暫存器偏移定址
這是arm特有的定址模式,當第2運算元是暫存器,在執行操作之前,可以做一次移位操作
mov r0,r2,lsl #3 ;r2的邏輯左移3位,結果放入r0,即r0=r2*8
ands r1,r1,r2,lsl r3;rs的值左移r3位,然後和r1相與操作,結果放入r1
移位操作有lsl (邏輯左移),lsr(邏輯右移) ,asr(算術右移),ror(迴圈右移)rrx帶擴充套件的迴圈右移
l 暫存器間接定址
即暫存器中值是一個地址,用來取出定位到地址當中
ldr r2,[r0] ;把r0的值當成地址,取出相應值,賦給r2
l 基址定址
把暫存器的地址值加上一個偏移量
ldr r2,[r3,#0x0f]; r3中的值加上0x0f,從這個地址取出值賦給r@
l 相對定址
基址定址的變形,由pc暫存器提供基準地址,指令中地址段作為偏移量.兩者相加即是有效地址,以下是bl採用相對定址
bl next
…next
…mov pc,lr ;從子程式返回
10. ads arm的偽指令
類似於c語言的巨集,由彙編程式預處理.
l 符號定義指令
全域性變數定義 gbla ,gbll,gbls
局域變數定義 lcla,lcll,lcls
變數賦值seta,setl,sets
其中上述偽指令中,最後面的a表示給一個算術變數賦值,l表示用於給一個邏輯變數賦值,s表示給一個字串賦值
gbll codedbg; 宣告一個全域性的邏輯變數
codebg setl ; 設定變數為
lcla bitno; 宣告一個算術變數
bitno seta 8 ;設變數值為8
l 資料定義偽指令
n space 定義一個記憶體空間,並用0初始化
space expr
databuf space 100 ;定義100位元組長空間, unsigned char databuf[100];
n dcb 定義一個連續位元組記憶體空間,用偽指令的表示式expr來初始化.一般可以用定義資料**,或文字字串.(這時等同於sets),用於初始二進位制buffer
dcb expr
dest dcb -120,20,36,55 ;等同於 unsigned char dest=;
n dcu定義的一段字的記憶體空間(dcb是位元組),並用後面表示式初始化
_reset dcu reset ; 等同於 dword _reset=;
n map定一個結構化記憶體,相當於定義一個c結構
n filed 定義一個結構化記憶體的成員
map 0x00,r9 ; 定義記憶體表,地址為r9
timer field 4 ; 定義資料域timer,長為4字
attrib field 4 ; 定義資料域attrib,長為4字
string filed 100 ; 定義資料域string ,長為100字
相當於c語言的定義:
struct r9;
11. 雜項的偽指令
n 位元組對齊 align
align; 宣告4位元組對齊
n 定義一個數字常量定義 equ
name equ expr
pllcon equ 0xe01fc080;定義pllcon,類似於c的巨集或c++的常量
n 包含檔案 get和include
include lpc2106.inc
n nop 空指令
在彙編時會被arm的空操作代替,比如mov r0,r0,一般用於延時與佔位。
n 宣告一個外部符符號 import,extern
import,extern 向外部匯入一個符號,一般是外部程式全域性變數
n 條件編譯:。類似於c的#ifdef 之類定義。
格式 :[ 條件表示式
滿足條件分支
|不滿足條件分支
]示例1:
[ entry_bus_width=32 ;類似#if entry_bus_width=32
b changebigendian ;dcd 0xea000007
] ; 類似#endif
示例2: [ clkdiv_val>1 ; 類似#if clkdiv_val>1
bl mmu_setasyncbusmode
|;類似#else
bl mmu_setfastbusmode ; default value.
]; 類似#endif
示例3 [ thumbcode 類似#ifdef thumbcode
bx lr
| ;類似#else
mov pc,lr
] ;類似#endif
n 段定義 area
n 指令集定義 code16和code32
指示是thumb 指令集(壓縮指令集,每個指令16位)。還是普通32位指令集
n 彙編結束:end
n 程式入口entry
使用組合語言,如何實現鍵盤控制數碼管顯示程式?如何對應鍵盤值在數碼管輸出相應的數值
line equ 30h row equ 31h val equ 32h org 00h start mov dptr,table 段碼錶首地址mov p2,00h 數碼管顯示初始化lscan mov p3,0f0h 列線置高電平,行線置高電平 l1 jnb p3.0,l2 逐行掃描lcall de...
Matlab如何實現樹結構,Matlab 如何實現樹結構
shine戚七七 由於matlab函式只能傳值傳遞引數的限制,操作起來稍有點不同。建立初始化連結串列空間 l,maintain initlist n,a1 a2 a3 例子 現在需要建立一樹,每個節點包含資料域,左指標域,和右指標域,估計需要的空間是100 l,maintain initlist 1...
請問如何在彙編中實現像c語言那樣if(k 7)than呼叫子程式Num
跳轉指令b 可以加上字尾eq變為beq表示 相等則跳轉 即當cpsr中的z標誌置位時發生跳轉。b 指令 b 指令的格式為 b 目標地址 b 指令是最簡單的跳轉指令。一旦遇到一個 b 指令,arm 處理器將立即跳轉到給定的目標地址,從那裡繼續執行。注意儲存在跳轉指令中的實際值是相對當前pc值的一個偏移...