ARM匯編語言中的偽操作(一)
符號定義( Symbol Definition )偽操作
符號定義偽操作用于定義 ARM 匯編程序中的變量、對變量賦值以及定義寄存器的別名。
包括以下偽操作:
— 用于聲明全局變量 GBLA 、 GBLL 和 GBLS 。
— 用于聲明局部變量 LCLA 、 LCLL 和 LCLS 。
— 用于對變量賦值 SETA 、 SETL 、 SETS 。
— 為通用寄存器列表定義名稱 RLIST 。
—為協(xié)處理器的寄存器定義名稱 CN
— 為協(xié)處理器定義名稱 CP
— 為VFP的寄存器定義名稱 DN、SN
— 為FPA的浮點寄存器定義名稱 FN
1、 GBLA、GBLL 和GBLS
語法格式:
GBLA ( GBLL 或 GBLS ) 全局變量名
GBLA 、 GBLL 和 GBLS 偽操作用于聲明一個 ARM 程序中的全局變量,并將其初始化。其中:
GBLA 偽操作用于聲明一個全局的算術(shù)變量,并初始化為 0 ;
GBLL 偽操作用于聲明一個全局的邏輯變量,并初始化為 {FALSE};
GBLS 偽操作用于聲明一個全局的字符串變量,并初始化為空串;
全局變量名在其作用范圍內(nèi)必須唯一。 如果用這些偽操作重新聲明已經(jīng)聲明過的變量,則變量的值將 被初始化成后一次聲明語句中的值。
使用示例:
GBLA Test1 ;聲明一個全局的算術(shù)變量,變量名為 Test1
Test1 SETA 0xaa ;將該變量賦值為 0xaa
SPACE Test1 ;引用該變量
GBLL Test2 ;聲明一個全局的邏輯變量,變量名為 Test2
Test2 SETL {TRUE} ;將該變量賦值為真
GBLS Test3 ;聲明一個全局的字符串變量,變量名為 Test3
Test3 SETS “ Testing ” ;將該變量賦值為 “ Testing ”
2、 LCLA、LCLL 和LCLS
語法格式:
LCLA ( LCLL 或 LCLS ) 局部變量名
LCLA 、 LCLL 和 LCLS 偽操作用于聲明一個 ARM 程序中的局部變量,并將其初始化。其中:
LCLA 偽操作用于聲明一個局部的數(shù)字變量,并初始化為 0 ;
LCLL 偽操作用于聲明一個局部的邏輯變量,并初始化為 {FALSE};
LCLS 偽操作用于聲明一個局部的字符串變量,并初始化為空串;
使用示例:
MACRO ;聲明一個宏
$label message $a ;宏的原型
LCLS err ;聲明一個局部串變量err
err SETS “error no: “ ;向該變量賦值
$label ;代碼
INFO 0, “err”:CC: :STR: $a ;使用該串變量
MEND ;宏定義結(jié)束
3、 SETA、SETL 和SETS
語法格式:
變量名 SETA ( SETL 或 SETS ) 表達式
偽操作 SETA 、 SETL 、 SETS 用于給一個ARM程序中的變量賦值。
SETA 偽操作用于給一個算術(shù)變量賦值;
SETL 偽操作用于給一個邏輯變量賦值;
SETS 偽操作用于給一個字符串變量賦值;
其中,變量名為已經(jīng)定義過的全局變量或局部變量,表達式為將要賦給變量的值。 在向變量賦值前,必須先聲明該變量。
4 、 RLIST
語法格式:
名稱 RLIST { 寄存器列表 }
RLIST 偽操作用于對一個通用寄存器列表定義名稱,定義的名稱可在LDM/STM指令中使用。在 LDM/STM 指令中,寄存器列表中的寄存器的訪問次序總是先訪問編號較低的寄存器,再訪問編號較高的寄存器,而不管寄存器列表中各寄存器的排列順序。
使用示例:
RegList RLIST {R0-R5 , R8 , R10} ;將寄存器列表名稱定義為 RegList ,可在 ARM 指令 LDM/STM中通過該名稱訪問寄存器列表。
5 、 CN
語法格式:
name CN expr
其中:name 是該寄存器的名稱
expr為協(xié)處理器的寄存器的編號,數(shù)值范圍為0~15。
CN偽操作用于給一個協(xié)處理器的寄存器定義名稱。方便程序員記憶該寄存器的功能
示例
Power CN 6 ;將協(xié)處理器的寄存器6名稱定義為Power
注:以下的偽操作類似(可參考CN)
數(shù)據(jù)定義( Data Definition )偽操作
數(shù)據(jù)定義偽操作包括以下偽操作:
LTORG 聲明一個數(shù)據(jù)緩沖池的開始;
MAP 定義一個結(jié)構(gòu)化的內(nèi)存表首地址;
FIELD 定義結(jié)構(gòu)化的內(nèi)存表中的一個數(shù)據(jù)域;
SPACE 分配一塊內(nèi)存單元,并用0初始化;
DCB 分配一段字節(jié)的內(nèi)存單元,并用指定的數(shù)據(jù)初始化;
DCD及DCDU 分配一段字的內(nèi)存單元,并用指定的數(shù)據(jù)初始化;
DCDO 分配一段字的內(nèi)存單元,并將每個單元的內(nèi)容初始化成該單元相對于基態(tài)值的寄存器的偏移量;
DCFD及DCFDU 分配一段雙字的內(nèi)存單元,并用雙精度的浮點數(shù)據(jù)初始化;
DCFS及DCFSU 分配一段字的內(nèi)存單元, 并用單精度的浮點數(shù)據(jù)初始化;
DCI 分配一段字節(jié)的內(nèi)存單元,用指定的數(shù)據(jù)初始化,指定內(nèi)存單元中存放的是代碼,而不是數(shù)據(jù);
DCQ及DCQU 分配一段雙字的內(nèi)存單元,并用64位的整數(shù)數(shù)據(jù)初始化;
DCW及DCWU 分配一段半字的內(nèi)存單元,并用指定的數(shù)據(jù)初始化;
DATA 在代碼段中使用數(shù)據(jù)(現(xiàn)在已不再使用,僅用于保持向前兼容)。
以下主要介紹幾種常用的:
1、 DCB (“ = ”)
語法格式:
標號 DCB 表達式
用于分配一段字節(jié)內(nèi)存單元并用偽操作中指定的表達式初始化。其中,表達式可以為 -128~ 255 的數(shù)值或字符串。
使用示例:
Str DCB “ This is a test ! ” ;分配一片連續(xù)的字節(jié)存儲單元并初始化。
2、DCD “ &”(或DCDU)
語法格式:
標號 DCD (或 DCDU ) 表達式
用于分配一段字內(nèi)存單元并用偽操作中指定的表達式初始化。其中,表達式可以為程序中的標號或數(shù)字表達式。
用DCD 分配的字存儲單元是字對齊的,而用 DCDU 分配的字存儲單元并不嚴格字對齊。
使用示例:
DataTest DCD 4,5,6 ;其值分別為4,5和6。
data2 DCD memaddr+4 ;分配一個字單元,其值為程序中標號memaddr加4個字節(jié)
3、DCQ(或DCQU)
語法格式:
標號 DCQ (或 DCQU ) 表達式
用于分配一段以8個字節(jié)為單位的內(nèi)存并用偽操作中指定的表達式初始化。
用 DCQ 分配的存儲單元是字對齊的,而用 DCQU 分配的存儲單元并不嚴格字對齊。
使用示例:
DataTest DCQ -255,2_101 ;2_101指的是二進制的101
4、 SPACE (“ % ”)
語法格式:
標號 SPACE 表達式
用于分配一塊內(nèi)存單元,并初始化為 0 。其中,表達式為要分配的字節(jié)數(shù)。
使用示例:
DataSpace SPACE 100 ;分配連續(xù) 100 字節(jié)的存儲單元并初始化為 0 。
5、 MAP (“ ^ ”)
語法格式:
MAP 表達式 { ,基址寄存器 }
用于定義一個結(jié)構(gòu)化的內(nèi)存表的首地址。
表達式可以為程序中的標號或數(shù)字表達式,基址寄存器為可選項,當基址寄存器選項不存在時,表達式的值即為內(nèi)存表的首地址,當該選項存在時,內(nèi)存表的首地址為表達式的值與基址寄存器的和。
MAP 偽操作通常與 FIELD 偽操作配合使用來定義結(jié)構(gòu)化的內(nèi)存表。
使用示例:
MAP 0x100 , R9;定義結(jié)構(gòu)化內(nèi)存表首地址的值為 0x100 + R9 。
6、 FILED (“ # ” )
語法格式:
標號 FIELD 表達式
用于定義一個結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域。
表達式的值為當前數(shù)據(jù)域在內(nèi)存表中所占的字節(jié)數(shù)。
FIELD 偽操作常與 MAP 偽操作配合使用來定義結(jié)構(gòu)化的內(nèi)存表結(jié)構(gòu)。 MAP 偽操作定義內(nèi)存表的首地址, FIELD 偽操作定義內(nèi)存表中的各數(shù)據(jù)域的字節(jié)長度,并可以為每個數(shù)據(jù)域指定一個標號供其他的指令引用。
注意 MAP 和 FIELD 偽操作僅用于定義數(shù)據(jù)結(jié)構(gòu),并不實際分配存儲單元。
示例1:
下面的偽操作序列定義一個內(nèi)存表,其首地址為固定地址4096,該內(nèi)存表中包括5個數(shù)據(jù)域:consta長度為4個字節(jié);constb長度為4個字節(jié);x長度為8個字節(jié);y長度為8個字節(jié);string長度為256個字節(jié)。這種內(nèi)存表稱為基于絕對地址的內(nèi)存表。
MAP 4096 ;內(nèi)存表的首地址為4096(0x1000)
consta FIELD 4 ;consta長度為4個字節(jié),相對位置為0
constb FIELD 4 ;constb長度為4個字節(jié),相對位置為5000
x FIELD 8 ;x長度為4個字節(jié),相對位置為5004
y FIELD 8 ;y長度為4個字節(jié),相對位置為5012
string FIELD 256 ;string長度為256字節(jié),相對位置為5020
;在指令中可以這樣引用內(nèi)存表中的數(shù)據(jù)域:
LDR R6,consta
上面的指令僅僅可以訪問LDR指令前面(或后面)4KB地址范圍的數(shù)據(jù)域
示例2:
下面的偽操作序列定義一個內(nèi)存表,其首地址為0,該內(nèi)存表中包括5個數(shù)據(jù)域:consta長度為4個字節(jié);constb長度為4個字節(jié);x長度為8個字節(jié);y長度為8個字節(jié);string長度為256個字節(jié)。這種內(nèi)存表稱為基于相對地址的內(nèi)存表。
MAP 4096 ;內(nèi)存表的首地址為0
consta FIELD 4 ;consta長度為4個字節(jié),相對位置為0
constb FIELD 4 ;constb長度為4個字節(jié),相對位置為4
x FIELD 8 ;x長度為4個字節(jié),相對位置為8
y FIELD 8 ;y長度為4個字節(jié),相對位置為16
string FIELD 256 ;string長度為256字節(jié),相對位置為24
;可以通過下面的指令方便地訪問地址范圍超過4KB的數(shù)據(jù)
MOV R9,#4096
LDR R5,[R9,constb] ;將內(nèi)存表中數(shù)據(jù)域constb讀取到R5中
在這里,內(nèi)存表中各數(shù)據(jù)域的實際內(nèi)存地址不是基于一個固定地址,而是基于LDR指令執(zhí)行時R9寄存器中的內(nèi)容。這樣通過上面方法定義的內(nèi)存表結(jié)構(gòu)可以在程序中有多個實例(通過在LDR指令中指定不同的基址寄存器值來實現(xiàn))。通常用R9作為靜態(tài)基址寄存器。
7、LTORG
用于聲明一個數(shù)據(jù)緩沖池(literal pool)的開始
通常ARM匯編編譯器把數(shù)據(jù)緩沖池放在代碼段的最后面,即下一個代碼段開始之前,或者END偽操作之前。
當程序中使用LDFD之類的指令時,數(shù)據(jù)緩沖池的使用可能越界。這時可以使用LTORG偽操作定義數(shù)據(jù)緩沖池,已越界發(fā)生。通常大的代碼段可以使用多個數(shù)據(jù)緩沖池。
LTORG偽操作通常放在無條件跳轉(zhuǎn)指令之后,或者子程序返回指令之后,這樣處理器就不會錯誤地將數(shù)據(jù)緩沖池中的數(shù)據(jù)當作指令來執(zhí)行。
匯編控制( Assembly Control )偽操作
匯編控制偽操作用于控制匯編程序的執(zhí)行流程,常用的匯編控制偽操作包括以下幾條:
— IF 、 ELSE 、 ENDIF
— WHILE 、 WEND
— MACRO 、 MEND
— MEXIT
1、 IF、ELSE、ENDIF
語法格式:
IF 邏輯表達式
指令序列 1
ELSE
指令序列 2
ENDIF
IF 、 ELSE 、 ENDIF 偽操作能根據(jù)條件把一段源代碼包括在匯編程序內(nèi)或者將其排除在程序之外。[是IF偽操作的同義詞,|是ELSE偽操作的同義詞,]是ENDIF偽操作的同義詞。
IF 、 ELSE 、 ENDIF 偽指令可以嵌套使用。
使用示例:
MACRO
MOV_PC_LR
[ THUMBCODE
bx lr
|
mov pc,lr
]
MEND
2、 WHILE、WEND
語法格式:
WHILE 邏輯表達式
指令序列
WEND
WHILE 、 WEND 偽操作能根據(jù)條件重復匯編相同的或者幾乎相同的一段源代碼。 WHILE 、 WEND 偽操作可以嵌套使用。
使用示例:
GBLA Counter ;聲明一個全局的算術(shù)變量,變量名為 counter
counter SETA 3 ;設置循環(huán)計數(shù)變量counter初始值為3
WHILE counter <=10 ;由counter控制循環(huán)執(zhí)行的次數(shù)
counter SETA counter+1 ;將循環(huán)計數(shù)變量加1
;代碼 ;代碼
WEND
3、 MACRO、MEND
語法格式:
MACRO
[$ label] macroname{ $ parameter1, $ parameter,…… }
指令序列
MEND
MACRO偽操作標識宏定義的開始,MEND標識宏定義的結(jié)束。用MACRO及MEND定義一段代碼,稱為宏定義體,這樣在程序中就可以通過宏指令多次調(diào)用該代碼段。
其中, $ label在宏指令被展開時,label會被替換成相應的符號,通常是一個標號。在一個符號前使用$表示程序被匯編時將使用相應的值來替代$后的符號。
macroname為所定義的宏的名稱。
$parameter為宏指令的參數(shù)。當宏指令被展開時將被替換成相應的值,類似于函數(shù)中的形式參數(shù),可以在宏定義時為參數(shù)指定相應的默認值。
宏指令的使用方式和功能與子程序有些相似,子程序可以提供模塊化的程序設計、節(jié)省存儲空間并提高運行速度。但在使用子程序結(jié)構(gòu)時需要保護現(xiàn)場,從而增加了系統(tǒng)的開銷,因此,在代碼較短且需要傳遞的參數(shù)較多時,可以使用宏匯編技術(shù)。
首先使用MACRO和MEND等偽操作定義宏。包含在 MACRO 和 MEND 之間的代碼段稱為宏定義體,在MACRO偽操作之后的一行聲明宏的原型(包含宏名、所需的參數(shù)),然后就可以在匯編程序中通過宏名來調(diào)用它。在源程序被匯編時,匯編器將宏調(diào)用展開,用宏定義體代替源程序中的宏定義的名稱,并用實際參數(shù)值代替宏定義時的形式參數(shù)。
宏定義中的$label是一個可選參數(shù)。當宏定義體中用到多個標號時,可以使用類似$label.$internallabel的標號命名規(guī)則使程序易讀。
MACRO 、 MEND 偽操作可以嵌套使用。
使用示例:
MACRO
$HandlerLabel HANDLER $HandleLabel ;宏的名稱為HANDLER,有1個參數(shù)$HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr r0,=$HandleLabel;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
MEND
;在程序中調(diào)用該宏
HandlerFIQ HANDLER HandleFIQ ;通過宏的名稱HANDLER調(diào)用宏,其中宏的標號為HandlerFIQ,參數(shù)為HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
;程序被匯編后,宏展開的結(jié)果
HandlerFIQ
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0} ;PUSH the work register to stack(lr does not push because it return to original address)
ldr r0,=HandleFIQ;load the address of HandleXXX to r0
ldr r0,[r0] ;load the contents(service routine start address) of HandleXXX
str r0,[sp,#4] ;store the contents(ISR) of HandleXXX to stack
ldmfd sp!,{r0,pc} ;POP the work register and pc(jump to ISR)
b HandlerUndef ;handler for Undefined mode
b HandlerSWI ;handler for SWI interrupt
b HandlerPabort ;handler for PAbort
b HandlerDabort ;handler for DAbort
b . ;reserved
b HandlerIRQ ;handler for IRQ interrupt
b HandlerFIQ ;handler for FIQ interrupt
4、 MEXIT
語法格式:
MEXIT
MEXIT 用于從宏定義中跳轉(zhuǎn)出去。
信息報告?zhèn)尾僮?br />ASSERT 斷言錯誤偽操作;
INFO 匯編診斷信息顯示偽操作;
OPT 設置列表選項偽操作;
TTL及SUBT 用于在列表文件每一項的開頭插入一個標題和子標題
評論