新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > ARM匯編語(yǔ)言中的偽操作(一)

ARM匯編語(yǔ)言中的偽操作(一)

作者: 時(shí)間:2016-11-11 來(lái)源:網(wǎng)絡(luò) 收藏
偽操作(derective)是ARM匯編語(yǔ)言程序里的一些特殊的指令助記符,其作用主要是為完成匯編程序做各種準(zhǔn)備工作,在源程序運(yùn)行匯編程序處理,而不是在計(jì)算機(jī)運(yùn)行期間有機(jī)器執(zhí)行.也就是說(shuō),這些偽操作只是匯編過(guò)程中起作用,一旦匯編結(jié)束,偽操作的使命也就隨之消失.

符號(hào)定義( Symbol Definition )偽操作
符號(hào)定義偽操作用于定義 ARM 匯編程序中的變量、對(duì)變量賦值以及定義寄存器的別名。
包括以下偽操作:
— 用于聲明全局變量 GBLA 、 GBLL 和 GBLS 。
— 用于聲明局部變量 LCLA 、 LCLL 和 LCLS 。
— 用于對(duì)變量賦值 SETA 、 SETL 、 SETS 。
— 為通用寄存器列表定義名稱 RLIST 。

本文引用地址:http://butianyuan.cn/article/201611/316615.htm

—為協(xié)處理器的寄存器定義名稱 CN
— 為協(xié)處理器定義名稱 CP
— 為VFP的寄存器定義名稱 DN、SN
— 為FPA的浮點(diǎn)寄存器定義名稱 FN

1、 GBLA、GBLL 和GBLS
語(yǔ)法格式:
GBLA ( GBLL 或 GBLS ) 全局變量名
GBLA 、 GBLL 和 GBLS 偽操作用于聲明一個(gè) ARM 程序中的全局變量,并將其初始化。其中:
GBLA 偽操作用于聲明一個(gè)全局的算術(shù)變量,并初始化為 0 ;
GBLL 偽操作用于聲明一個(gè)全局的邏輯變量,并初始化為 {FALSE};
GBLS 偽操作用于聲明一個(gè)全局的字符串變量,并初始化為空串;
全局變量名在其作用范圍內(nèi)必須唯一。 如果用這些偽操作重新聲明已經(jīng)聲明過(guò)的變量,則變量的值將 被初始化成后一次聲明語(yǔ)句中的值。
使用示例:
GBLA Test1 ;聲明一個(gè)全局的算術(shù)變量,變量名為 Test1
Test1 SETA 0xaa ;將該變量賦值為 0xaa
SPACE Test1 ;引用該變量

GBLL Test2 ;聲明一個(gè)全局的邏輯變量,變量名為 Test2
Test2 SETL {TRUE} ;將該變量賦值為真
GBLS Test3 ;聲明一個(gè)全局的字符串變量,變量名為 Test3
Test3 SETS “ Testing ” ;將該變量賦值為 “ Testing ”

2、 LCLA、LCLL 和LCLS
語(yǔ)法格式:
LCLA ( LCLL 或 LCLS ) 局部變量名
LCLA 、 LCLL 和 LCLS 偽操作用于聲明一個(gè) ARM 程序中的局部變量,并將其初始化。其中:
LCLA 偽操作用于聲明一個(gè)局部的數(shù)字變量,并初始化為 0 ;
LCLL 偽操作用于聲明一個(gè)局部的邏輯變量,并初始化為 {FALSE};
LCLS 偽操作用于聲明一個(gè)局部的字符串變量,并初始化為空串;
使用示例:
MACRO ;聲明一個(gè)宏

$label message $a ;宏的原型

LCLS err ;聲明一個(gè)局部串變量err

err SETS “error no: “ ;向該變量賦值

$label ;代碼

INFO 0, “err”:CC: :STR: $a ;使用該串變量

MEND ;宏定義結(jié)束

3、 SETA、SETL 和SETS
語(yǔ)法格式:
變量名 SETA ( SETL 或 SETS ) 表達(dá)式
偽操作 SETA 、 SETL 、 SETS 用于給一個(gè)ARM程序中的變量賦值。
SETA 偽操作用于給一個(gè)算術(shù)變量賦值;
SETL 偽操作用于給一個(gè)邏輯變量賦值;
SETS 偽操作用于給一個(gè)字符串變量賦值;
其中,變量名為已經(jīng)定義過(guò)的全局變量或局部變量,表達(dá)式為將要賦給變量的值。 在向變量賦值前,必須先聲明該變量。

4 、 RLIST
語(yǔ)法格式:
名稱 RLIST { 寄存器列表 }
RLIST 偽操作用于對(duì)一個(gè)通用寄存器列表定義名稱,定義的名稱可在LDM/STM指令中使用。在 LDM/STM 指令中,寄存器列表中的寄存器的訪問(wèn)次序總是先訪問(wèn)編號(hào)較低的寄存器,再訪問(wèn)編號(hào)較高的寄存器,而不管寄存器列表中各寄存器的排列順序。

使用示例:
RegList RLIST {R0-R5 , R8 , R10} ;將寄存器列表名稱定義為 RegList ,可在 ARM 指令 LDM/STM中通過(guò)該名稱訪問(wèn)寄存器列表。


5 、 CN

語(yǔ)法格式:

name CN expr

其中:name 是該寄存器的名稱

expr為協(xié)處理器的寄存器的編號(hào),數(shù)值范圍為0~15。

CN偽操作用于給一個(gè)協(xié)處理器的寄存器定義名稱。方便程序員記憶該寄存器的功能

示例

Power CN 6 ;將協(xié)處理器的寄存器6名稱定義為Power

注:以下的偽操作類似(可參考CN)

數(shù)據(jù)定義( Data Definition )偽操作
數(shù)據(jù)定義偽操作包括以下偽操作:

LTORG 聲明一個(gè)數(shù)據(jù)緩沖池的開始;

MAP 定義一個(gè)結(jié)構(gòu)化的內(nèi)存表首地址;

FIELD 定義結(jié)構(gòu)化的內(nèi)存表中的一個(gè)數(shù)據(jù)域;

SPACE 分配一塊內(nèi)存單元,并用0初始化;

DCB 分配一段字節(jié)的內(nèi)存單元,并用指定的數(shù)據(jù)初始化;

DCD及DCDU 分配一段字的內(nèi)存單元,并用指定的數(shù)據(jù)初始化;

DCDO 分配一段字的內(nèi)存單元,并將每個(gè)單元的內(nèi)容初始化成該單元相對(duì)于基態(tài)值的寄存器的偏移量;

DCFD及DCFDU 分配一段雙字的內(nèi)存單元,并用雙精度的浮點(diǎn)數(shù)據(jù)初始化;

DCFS及DCFSU 分配一段字的內(nèi)存單元, 并用單精度的浮點(diǎn)數(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 (“ = ”)
語(yǔ)法格式:
標(biāo)號(hào) DCB 表達(dá)式
用于分配一段字節(jié)內(nèi)存單元并用偽操作中指定的表達(dá)式初始化。其中,表達(dá)式可以為 -128~ 255 的數(shù)值或字符串。
使用示例:
Str DCB “ This is a test ! ” ;分配一片連續(xù)的字節(jié)存儲(chǔ)單元并初始化。

2、DCD “ &”(或DCDU)
語(yǔ)法格式:
標(biāo)號(hào) DCD (或 DCDU ) 表達(dá)式
用于分配一段字內(nèi)存單元并用偽操作中指定的表達(dá)式初始化。其中,表達(dá)式可以為程序中的標(biāo)號(hào)或數(shù)字表達(dá)式。

用DCD 分配的字存儲(chǔ)單元是字對(duì)齊的,而用 DCDU 分配的字存儲(chǔ)單元并不嚴(yán)格字對(duì)齊。
使用示例:
DataTest DCD 4,5,6 ;其值分別為4,5和6。
data2 DCD memaddr+4 ;分配一個(gè)字單元,其值為程序中標(biāo)號(hào)memaddr加4個(gè)字節(jié)
3、DCQ(或DCQU)
語(yǔ)法格式:
標(biāo)號(hào) DCQ (或 DCQU ) 表達(dá)式
用于分配一段以8個(gè)字節(jié)為單位的內(nèi)存并用偽操作中指定的表達(dá)式初始化。
用 DCQ 分配的存儲(chǔ)單元是字對(duì)齊的,而用 DCQU 分配的存儲(chǔ)單元并不嚴(yán)格字對(duì)齊。
使用示例:
DataTest DCQ -255,2_101 ;2_101指的是二進(jìn)制的101

4、 SPACE (“ % ”)
語(yǔ)法格式:
標(biāo)號(hào) SPACE 表達(dá)式
用于分配一塊內(nèi)存單元,并初始化為 0 。其中,表達(dá)式為要分配的字節(jié)數(shù)。
使用示例:
DataSpace SPACE 100 ;分配連續(xù) 100 字節(jié)的存儲(chǔ)單元并初始化為 0 。

5、 MAP (“ ^ ”)
語(yǔ)法格式:
MAP 表達(dá)式 { ,基址寄存器 }
用于定義一個(gè)結(jié)構(gòu)化的內(nèi)存表的首地址。
表達(dá)式可以為程序中的標(biāo)號(hào)或數(shù)字表達(dá)式,基址寄存器為可選項(xiàng),當(dāng)基址寄存器選項(xiàng)不存在時(shí),表達(dá)式的值即為內(nèi)存表的首地址,當(dāng)該選項(xiàng)存在時(shí),內(nèi)存表的首地址為表達(dá)式的值與基址寄存器的和。
MAP 偽操作通常與 FIELD 偽操作配合使用來(lái)定義結(jié)構(gòu)化的內(nèi)存表。
使用示例:
MAP 0x100 , R9;定義結(jié)構(gòu)化內(nèi)存表首地址的值為 0x100 + R9 。

6、 FILED (“ # ” )
語(yǔ)法格式:
標(biāo)號(hào) FIELD 表達(dá)式
用于定義一個(gè)結(jié)構(gòu)化內(nèi)存表中的數(shù)據(jù)域。
表達(dá)式的值為當(dāng)前數(shù)據(jù)域在內(nèi)存表中所占的字節(jié)數(shù)。
FIELD 偽操作常與 MAP 偽操作配合使用來(lái)定義結(jié)構(gòu)化的內(nèi)存表結(jié)構(gòu)。 MAP 偽操作定義內(nèi)存表的首地址, FIELD 偽操作定義內(nèi)存表中的各數(shù)據(jù)域的字節(jié)長(zhǎng)度,并可以為每個(gè)數(shù)據(jù)域指定一個(gè)標(biāo)號(hào)供其他的指令引用。
注意 MAP 和 FIELD 偽操作僅用于定義數(shù)據(jù)結(jié)構(gòu),并不實(shí)際分配存儲(chǔ)單元。
示例1:
下面的偽操作序列定義一個(gè)內(nèi)存表,其首地址為固定地址4096,該內(nèi)存表中包括5個(gè)數(shù)據(jù)域:consta長(zhǎng)度為4個(gè)字節(jié);constb長(zhǎng)度為4個(gè)字節(jié);x長(zhǎng)度為8個(gè)字節(jié);y長(zhǎng)度為8個(gè)字節(jié);string長(zhǎng)度為256個(gè)字節(jié)。這種內(nèi)存表稱為基于絕對(duì)地址的內(nèi)存表。

MAP 4096 ;內(nèi)存表的首地址為4096(0x1000)

consta FIELD 4 ;consta長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為0

constb FIELD 4 ;constb長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為5000

x FIELD 8 ;x長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為5004

y FIELD 8 ;y長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為5012

string FIELD 256 ;string長(zhǎng)度為256字節(jié),相對(duì)位置為5020

;在指令中可以這樣引用內(nèi)存表中的數(shù)據(jù)域:

LDR R6,consta

上面的指令僅僅可以訪問(wèn)LDR指令前面(或后面)4KB地址范圍的數(shù)據(jù)域

示例2:

下面的偽操作序列定義一個(gè)內(nèi)存表,其首地址為0,該內(nèi)存表中包括5個(gè)數(shù)據(jù)域:consta長(zhǎng)度為4個(gè)字節(jié);constb長(zhǎng)度為4個(gè)字節(jié);x長(zhǎng)度為8個(gè)字節(jié);y長(zhǎng)度為8個(gè)字節(jié);string長(zhǎng)度為256個(gè)字節(jié)。這種內(nèi)存表稱為基于相對(duì)地址的內(nèi)存表。

MAP 4096 ;內(nèi)存表的首地址為0

consta FIELD 4 ;consta長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為0

constb FIELD 4 ;constb長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為4

x FIELD 8 ;x長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為8

y FIELD 8 ;y長(zhǎng)度為4個(gè)字節(jié),相對(duì)位置為16

string FIELD 256 ;string長(zhǎng)度為256字節(jié),相對(duì)位置為24

;可以通過(guò)下面的指令方便地訪問(wèn)地址范圍超過(guò)4KB的數(shù)據(jù)

MOV R9,#4096

LDR R5,[R9,constb] ;將內(nèi)存表中數(shù)據(jù)域constb讀取到R5中

在這里,內(nèi)存表中各數(shù)據(jù)域的實(shí)際內(nèi)存地址不是基于一個(gè)固定地址,而是基于LDR指令執(zhí)行時(shí)R9寄存器中的內(nèi)容。這樣通過(guò)上面方法定義的內(nèi)存表結(jié)構(gòu)可以在程序中有多個(gè)實(shí)例(通過(guò)在LDR指令中指定不同的基址寄存器值來(lái)實(shí)現(xiàn))。通常用R9作為靜態(tài)基址寄存器。

7、LTORG

用于聲明一個(gè)數(shù)據(jù)緩沖池(literal pool)的開始

通常ARM匯編編譯器把數(shù)據(jù)緩沖池放在代碼段的最后面,即下一個(gè)代碼段開始之前,或者END偽操作之前。

當(dāng)程序中使用LDFD之類的指令時(shí),數(shù)據(jù)緩沖池的使用可能越界。這時(shí)可以使用LTORG偽操作定義數(shù)據(jù)緩沖池,已越界發(fā)生。通常大的代碼段可以使用多個(gè)數(shù)據(jù)緩沖池。

LTORG偽操作通常放在無(wú)條件跳轉(zhuǎn)指令之后,或者子程序返回指令之后,這樣處理器就不會(huì)錯(cuò)誤地將數(shù)據(jù)緩沖池中的數(shù)據(jù)當(dāng)作指令來(lái)執(zhí)行。

匯編控制( Assembly Control )偽操作
匯編控制偽操作用于控制匯編程序的執(zhí)行流程,常用的匯編控制偽操作包括以下幾條:
— IF 、 ELSE 、 ENDIF
— WHILE 、 WEND
— MACRO 、 MEND
— MEXIT
1、 IF、ELSE、ENDIF
語(yǔ)法格式:
IF 邏輯表達(dá)式
指令序列 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
語(yǔ)法格式:
WHILE 邏輯表達(dá)式
指令序列
WEND
WHILE 、 WEND 偽操作能根據(jù)條件重復(fù)匯編相同的或者幾乎相同的一段源代碼。 WHILE 、 WEND 偽操作可以嵌套使用。
使用示例:
GBLA Counter ;聲明一個(gè)全局的算術(shù)變量,變量名為 counter
counter SETA 3 ;設(shè)置循環(huán)計(jì)數(shù)變量counter初始值為3
WHILE counter <=10 ;由counter控制循環(huán)執(zhí)行的次數(shù)
counter SETA counter+1 ;將循環(huán)計(jì)數(shù)變量加1
;代碼 ;代碼
WEND

3、 MACRO、MEND
語(yǔ)法格式:
MACRO
[$ label] macroname{ $ parameter1, $ parameter,…… }
指令序列
MEND
MACRO偽操作標(biāo)識(shí)宏定義的開始,MEND標(biāo)識(shí)宏定義的結(jié)束。用MACRO及MEND定義一段代碼,稱為宏定義體,這樣在程序中就可以通過(guò)宏指令多次調(diào)用該代碼段。
其中, $ label在宏指令被展開時(shí),label會(huì)被替換成相應(yīng)的符號(hào),通常是一個(gè)標(biāo)號(hào)。在一個(gè)符號(hào)前使用$表示程序被匯編時(shí)將使用相應(yīng)的值來(lái)替代$后的符號(hào)。
macroname為所定義的宏的名稱。
$parameter為宏指令的參數(shù)。當(dāng)宏指令被展開時(shí)將被替換成相應(yīng)的值,類似于函數(shù)中的形式參數(shù),可以在宏定義時(shí)為參數(shù)指定相應(yīng)的默認(rèn)值。
宏指令的使用方式和功能與子程序有些相似,子程序可以提供模塊化的程序設(shè)計(jì)、節(jié)省存儲(chǔ)空間并提高運(yùn)行速度。但在使用子程序結(jié)構(gòu)時(shí)需要保護(hù)現(xiàn)場(chǎng),從而增加了系統(tǒng)的開銷,因此,在代碼較短且需要傳遞的參數(shù)較多時(shí),可以使用宏匯編技術(shù)。
首先使用MACRO和MEND等偽操作定義宏。包含在 MACRO 和 MEND 之間的代碼段稱為宏定義體,在MACRO偽操作之后的一行聲明宏的原型(包含宏名、所需的參數(shù)),然后就可以在匯編程序中通過(guò)宏名來(lái)調(diào)用它。在源程序被匯編時(shí),匯編器將宏調(diào)用展開,用宏定義體代替源程序中的宏定義的名稱,并用實(shí)際參數(shù)值代替宏定義時(shí)的形式參數(shù)。
宏定義中的$label是一個(gè)可選參數(shù)。當(dāng)宏定義體中用到多個(gè)標(biāo)號(hào)時(shí),可以使用類似$label.$internallabel的標(biāo)號(hào)命名規(guī)則使程序易讀。
MACRO 、 MEND 偽操作可以嵌套使用。
使用示例:
MACRO
$HandlerLabel HANDLER $HandleLabel ;宏的名稱為HANDLER,有1個(gè)參數(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 ;通過(guò)宏的名稱HANDLER調(diào)用宏,其中宏的標(biāo)號(hà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
語(yǔ)法格式:
MEXIT
MEXIT 用于從宏定義中跳轉(zhuǎn)出去。
信息報(bào)告?zhèn)尾僮?br />ASSERT 斷言錯(cuò)誤偽操作;
INFO 匯編診斷信息顯示偽操作;
OPT 設(shè)置列表選項(xiàng)偽操作;
TTL及SUBT 用于在列表文件每一項(xiàng)的開頭插入一個(gè)標(biāo)題和子標(biāo)題



關(guān)鍵詞: ARM匯編語(yǔ)言偽操

評(píng)論


技術(shù)專區(qū)

關(guān)閉