当前位置:文档之家› 在ARM处理器汇编伪指令

在ARM处理器汇编伪指令

在ARM处理器汇编伪指令
在ARM处理器汇编伪指令

在ARM处理器汇编语言程序设计里,有一些特殊的指令助记符。这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊的指令助记符为伪指令,它们所完成的操作称为伪操作。

伪指令在源程序中的作用是为完成汇编程序做各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成了。在ARM处理器的汇编程序中,大体有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令及其他伪指令。伪操作符可以分为以下几类。

1)数据定义伪操作符

数据定义伪操作符主要包括LTORG、MAP、DCB、FIELD、SPACE、DCQ、DCW等,主要用于数据表定义、文字池定义、数据空间分配等。常用的有DCB/DCQ/DCW分配一段字节/双字/字内存单元,并且将它们初始化。

2)符号定义伪操作符

符号定义伪操作符包括GBLA、GBLL、GBLS、LCLA、CN、CP、DN、FN、RLIST、SETA 等,用于定义ARM汇编程序的变量,对变量进行赋值,以及定义寄存器名称等。其中用于全局变量声明的GBLA、GBLL、GBLS和局部变量声明的LCAL、LCLL、LCLS伪指令较为常用。

3)报告伪操作符

报告伪操作符包括ASSERT、INFO、OPT等,主要用于汇编报告等。其中比较常用的有ASSERT,表示断言错误。

4)条件汇编伪操作符

条件汇编伪操作符包括IF、ELSE、ENDIF、WHIL、WEND、MACRO、MEND等,主要用于条件汇编、宏定义、重复汇编控制等操作。

5)杂项伪操作符

杂项伪操作符包括AREA、ALIGN、ENTRY、EQU、EXPORT、GLOBAL、IMPORT、CODE16、CODE32等。这些伪指令在汇编程序设计中较为常用,如段定义、入口点设置等伪指令。常用的伪指令主要有以下几条。

AREA:用来定义段;

ALIGN:用来设定边界对齐;

CODE16/CODE32:用来指定指令集;

ENTRY:指定程序入口;

END:汇编结束。

在ARM 汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊指令助记符为伪指令,他们所完成的操作称为伪操作。

伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。https://www.doczj.com/doc/0813002581.html,1 V* ?: A2 c1 L

https://www.doczj.com/doc/0813002581.html,% r' m' B a" j% I9 U

在ARM 的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。https://www.doczj.com/doc/0813002581.html,2 v3 w5 X$ G4 E. L: a

1 r B n- J" j- J' Z p

符号定义(Symbol Definition )伪指令

符号定义伪指令用于定义ARM 汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。Y! |# q" F! /& x$ x

常见的符号定义伪指令有如下几种:

—用于定义全局变量的GBLA 、GBLL 和GBLS 。CEDN论坛& V) {7 M, d' S' _—用于定义局部变量的LCLA 、LCLL 和LCLS 。

—用于对变量赋值的SETA 、SETL 、SETS 。

—为通用寄存器列表定义名称的RLIST 。https://www.doczj.com/doc/0813002581.html, ?7 x; t; I4 h* `

1、GBLA、GBLL 和GBLS / q: X* X- W' v5 [3 v2 {4 Q

语法格式:https://www.doczj.com/doc/0813002581.html,6 K, E9 M, s9 i5 U

GBLA (GBLL 或GBLS )全局变量名

GBLA 、GBLL 和GBLS 伪指令用于定义一个ARM 程序中的全局变量,并将其初始化。其中:

GBLA 伪指令用于定义一个全局的数字变量,并初始化为0 ;https://www.doczj.com/doc/0813002581.html,% /6 M+ b/ U% W+ b" U3 F

GBLL 伪指令用于定义一个全局的逻辑变量,并初始化为F (假);https://www.doczj.com/doc/0813002581.html,: E! r/ ~0 / o) ]

GBLS 伪指令用于定义一个全局的字符串变量,并初始化为空;

由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。

使用示例:

GBLA Test1 ;定义一个全局的数字变量,变量名为Test1 0 _: m2 v& L4 G3 b; L C Test1 SETA 0xaa ;将该变量赋值为0xaa

GBLL Test2 ;定义一个全局的逻辑变量,变量名为Test2 s% ^3 /8 U& R% G

Test2 SETL {TRUE} ;将该变量赋值为真

GBLS Test3 ;定义一个全局的字符串变量,变量名为Test3 - {( Q a* c* S* P, z% B Test3 SETS “ Testing ”;将该变量赋值为“ Testing ”

2、LCLA、LCLL 和LCLS

语法格式:: e6 E2 F7 V! O* C0 H3 /

LCLA (LCLL 或LCLS )局部变量名https://www.doczj.com/doc/0813002581.html,$ p% F+ J! s( @, E$ @

LCLA 、LCLL 和LCLS 伪指令用于定义一个ARM 程序中的局部变量,并将其初始化。其中:

LCLA 伪指令用于定义一个局部的数字变量,并初始化为0 ; 1 K3 ~* I. C4 F* I! ?7 L: f7 X, N

LCLL 伪指令用于定义一个局部的逻辑变量,并初始化为F (假);

LCLS 伪指令用于定义一个局部的字符串变量,并初始化为空;0 K5 v( |# f6 u

以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。

使用示例:

LCLA Test4 ;声明一个局部的数字变量,变量名为Test4 2 k3 K5 R4 w| k h7 c) E! L

Test3 SETA 0xaa ;将该变量赋值为0xaa

LCLL Test5 ;声明一个局部的逻辑变量,变量名为Test5 % P9 /$ [/ y% t& f

Test4 SETL {TRUE} ;将该变量赋值为真. T! z) p# /. i5 ~

LCLS Test6 ;定义一个局部的字符串变量,变量名为Test6 + n0 /1 n" X/ O$ @: [

Test6 SETS “ Testing ”;将该变量赋值为“ Testing ”

, }7 @% v2 s$ Z' C; H8 W

3、SETA、SETL 和SETS

语法格式: 5 T2 A/ M" F* A+ S. ~3 p4 /$ I8 n8 o

变量名SETA (SETL 或SETS )表达式 1 U' L% w, B/ A+ R0 M' S: _

伪指令SETA 、SETL 、SETS 用于给一个已经定义的全局变量或局部变量赋值。

https://www.doczj.com/doc/0813002581.html, X8 q$ C0 {7 n& N

SETA 伪指令用于给一个数学变量赋值; 3 @6 y, Y' B5 t8 K9 M1 [) [6 /& U4 B

SETL 伪指令用于给一个逻辑变量赋值; 6 o5 M. J6 Y2 y; l& Q( v

SETS 伪指令用于给一个字符串变量赋值; 4 {) t" u0 ~0 N1 /7 Q2 k2 p

其中,变量名为已经定义过的全局变量或局部变量,表达式为将要赋给变量的值。

使用示例:

LCLA Test3 ;声明一个局部的数字变量,变量名为Test3 & z, s/ k7 C9 h/ f4 |

Test3 SETA 0xaa ;将该变量赋值为0xaa ' k, M" s# K, Q ~% t

LCLL Test4 ;声明一个局部的逻辑变量,变量名为Test4

Test4 SETL {TRUE} ;将该变量赋值为真CEDN论坛/ ~' @" E2 m* M( P

4 、RLIST

语法格式:

名称RLIST { 寄存器列表} CE DN论坛% b P2 a8 g7 i% ?

RLIST 伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在ARM 指令LDM/STM 中使用。在LDM/STM 指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。CEDN论坛6 }+ W$ u* c& c7 o8 a 使用示例:

RegList RLIST {R0-R5 ,R8 ,R10} ;将寄存器列表名称定义为RegList ,可在ARM 指令LDM/STM中通过该名称访问寄存器列表。

/ i6 `/ X: R+ w# s' F; A) L

数据定义(Data Definition )伪指令

数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。

常见的数据定义伪指令有如下几种:

— DCB 用于分配一片连续的字节存储单元并用指定的数据初始化。' B) Y r6 A, W — DCW (DCWU )用于分配一片连续的半字存储单元并用指定的数据初始化。

1 V6 |1 L1 F' /: w

— DCD (DCDU )用于分配一片连续的字存储单元并用指定的数据初始化。

— DCFD (DCFDU )用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始

化。https://www.doczj.com/doc/0813002581.html,2 c! J/ f% z/ `

— DCFS (DCFSU )用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初https://www.doczj.com/doc/0813002581.html,- g' Z8 U, m# R/ q

始化。https://www.doczj.com/doc/0813002581.html,- /! f" f6 M A( M8 M) |

— DCQ (DCQU )用于分配一片以8 字节为单位的连续的存储单元并用指定的数据初始

化。

— SPACE 用于分配一片连续的存储单元CEDN论坛* `+ a2 @8 y3 M! d3 c, b5 q- N+ j

— MAP 用于定义一个结构化的内存表首地址

— FIELD 用于定义一个结构化的内存表的数据域https://www.doczj.com/doc/0813002581.html,5 E2 ?3 q/ V: a$ R* J6 E% L$ [

1、DCB . B `) _# i( i

语法格式:https://www.doczj.com/doc/0813002581.html,3 G6 g0 z8 c. S; u% o

标号DCB 表达式

DCB 伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为0 ~255 的数字或字符串。DCB 也可用“ = ”代替。

使用示例: 1 o+ x' Y) u, p. M' B; _

Str DCB “ This is a test !”;分配一片连续的字节存储单元并初始化。CE DN论坛. u:

i7 e1 c- D1 ]

2、DCW(或DCWU)CEDN论坛4 R c2 H% z2 K: n

语法格式:

标号DCW (或DCWU )表达式

DCW (或DCWU )伪指令用于分配一片连续的半字存储单元并用伪指令中指定的表达式初始化。

其中,表达式可以为程序标号或数字表达式。。

用DCW 分配的字存储单元是半字对齐的,而用DCWU 分配的字存储单元并不严格半字对齐。

使用示例:

DataTest DCW 1 ,2 ,3 ;分配一片连续的半字存储单元并初始化。

3、DCD(或DCDU)# d q! /, _ T5 C- T0 J

语法格式:" i- ?' [# R N5 L

标号DCD (或DCDU )表达式0 p' I( G# J8 m ]5 P

DCD (或DCDU )伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。DCD 也可用“ & ”代替。9 G3 r2 F( c+ D& R ]. Q; q9 s$ Q

用DCD 分配的字存储单元是字对齐的,而用DCDU 分配的字存储单元并不严格字对齐。, e+ g; W /5 Q# I5 ?5 / _0 n

使用示例:

DataTest DCD 4 ,5 ,6 ;分配一片连续的字存储单元并初始化。

https://www.doczj.com/doc/0813002581.html,9 R1 E+ W. I) r: G# I$ C6 A4 m

4、DCFD(或DCFDU)

语法格式:

标号DCFD (或DCFDU )表达式

DCFD (或DCFDU )伪指令用于为双精度的浮点数分配一片连续的字存储单元并用伪指令中指定的表达式初始化。每个双精度的浮点数占据两个字单元。用DCFD 分配的字存储单元是字对齐的,而用DCFDU 分配的字存储单元并不严格字对齐。& p% e8 |" B0 |# F! A# e9 T( s

使用示例:CEDN论坛* I. V4 S% c- b: x0 ]/ A! U

FDataTest DCFD 2E115 ,-5E7 ;分配一片连续的字存储单元并初始化为指定的双精度数。! A4 a9 K& f' B5 t _( ]

9 x! q& Q# ^; ~9 t4 v# i6 y

5、DCFS(或DCFSU)

语法格式:, q# b& R' y/ o0 x! C$ a

标号DCFS (或DCFSU )表达式

DCFS (或DCFSU )伪指令用于为单精度的浮点数分配一片连续的字存储单元并用伪指令中指定的表达式初始化。每个单精度的浮点数占据一个字单元。用DCFS 分配的字存储单元是字对齐的,而用DCFSU 分配的字存储单元并不严格字对齐。

使用示例:: e' ^, S" u# H4 X8 b- U5 m2 y

FDataTest DCFS 2E5 ,-5E -7 ;分配一片连续的字存储单元并初始化为指定的单精度数。

6、DCQ(或DCQU) 5 a' ?8 C/ D1 b4 H( L8 g1 t

语法格式:' ]1 k- G- r- M4 s* u# E) w! k

标号DCQ (或DCQU )表达式0 N3 k, T$ m+ a1 k9 Q

DCQ (或DCQU )伪指令用于分配一片以8 个字节为单位的连续存储区域并用伪指令中指定的表达式初始化。. p7 t f$ u9 y% `$ g: u

用DCQ 分配的存储单元是字对齐的,而用DCQU 分配的存储单元并不严格字对齐。

使用示例:$ A P6 o: y, W# v6 D

DataTest DCQ 100 ;分配一片连续的存储单元并初始化为指定的值。

) E" Q- _* F' U

7、SPACE 7 j6 F z* S4 N1 V. J3 /

语法格式:

标号SPACE 表达式- K7 ]' L4 `) T4 @8 H

SPACE 伪指令用于分配一片连续的存储区域并初始化为0 。其中,表达式为要分配的字节数。

SPACE 也可用“%”代替。

使用示例:CEDN论坛: t+ m4 S! h: [( /- E

DataSpace SPACE 100 ;分配连续100 字节的存储单元并初始化为0 。

: t; R$ [. D2 r& r6 v* N

8、MAP CE DN论坛: N% S: A4 U, q

语法格式:! w+ H" V5 D! h# L& ~* z

MAP 表达式{ ,基址寄存器} N* D s: j3 @. L' X

MAP 伪指令用于定义一个结构化的内存表的首地址。MAP 也可用“^”代替。

表达式可以为程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不

存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。: f& A) g8 r7 ]2 h+ `( ^' r1 p

MAP 伪指令通常与FIELD 伪指令配合使用来定义结构化的内存表。. m; v" V/ s4 U" x: T+ c+ m( /0 D3 [. I

使用示例:

MAP 0x100 ,R0 ;定义结构化内存表首地址的值为0x100 +R0 。

; ]0 T- V4 T, K4 Y0 M" J3 X

9、FILED

语法格式:

标号FIELD 表达式

FIELD 伪指令用于定义一个结构化内存表中的数据域。FILED 也可用“ # ”代替。

表达式的值为当前数据域在内存表中所占的字节数。

FIELD 伪指令常与MAP 伪指令配合使用来定义结构化的内存表。MAP 伪指令定义内存表的首地址,FIELD 伪指令定义内存表中的各个数据域,并可以为每个数据域指定一个标号供其他的指令引用。

注意MAP 和FIELD 伪指令仅用于定义数据结构,并不实际分配存储单元。. _% m$ c& H$ y3 F! @

使用示例:

MAP 0x100 ;定义结构化内存表首地址的值为0x100 。

A FIELD 16 ;定义A 的长度为16 字节,位置为0x100

B FIELD 32 ;定义B 的长度为32 字节,位置为0x110

S FIELD 256 ;定义S 的长度为256 字节,位置为0x130 9 U% [( D( y9 r* P3 [0 T

# E( J0 D# E U: A9 w

汇编控制(Assembly Control )伪指令CE DN论坛8 ^7 X, n8 C; T4 R: X% j

汇编控制伪指令用于控制汇编程序的执行流程,常用的汇编控制伪指令包括以下几条:

— IF 、ELSE 、ENDIF 6 `( n% ~2 ?- ~3 j: Y# N

— WHILE 、WEND 6 h8 x/ Z" N+ z( Q7 X

— MACRO 、MEND , u; r2 F g; _: X% W) @

— MEXIT ( F9 G' p6 /6 V( `, [1 Z5 G: L

1、IF、ELSE、ENDIF https://www.doczj.com/doc/0813002581.html,5 i3 w7 X' J4 N7 o3 ]2 C8 K g- b

语法格式: 1 a1 n4 Z* Y4 U& N7 n

IF 逻辑表达式

指令序列1

ELSE

指令序列2 CE DN论坛) c3 X4 `% r# C, q! P7 K( c

ENDIF 7 v. }) o% g* ]2 U* V

IF 、ELSE 、ENDIF 伪指令能根据条件的成立与否决定是否执行某个指令序列。当IF 后面的逻辑表达式为真,则执行指令序列1 ,否则执行指令序列2 。其中,ELSE 及指令序列2 可以没有,此时,当IF 后面的逻辑表达式为真,则执行指令序列1 ,否则继续执行后面的指令。

IF 、ELSE 、ENDIF 伪指令可以嵌套使用。

使用示例:

GBLL Test ;声明一个全局的逻辑变量,变量名为Test……

IF Test = TRUE

指令序列1

ELSE / u0 ?9 g. `( p4 q5 o6 L6 V$ ~

指令序列2 . Z1 S! i9 S# M: g- f. {' F

ENDIF ( e( `9 [3 ^( B$ k

* g7 c1 R3 g8 W& A I. U* R0 J

2、WHILE、WEND ' |) C1 |* b# /* K7 ]/ U

语法格式:https://www.doczj.com/doc/0813002581.html,. F0 U& D% W( R7 q( g H

WHILE 逻辑表达式https://www.doczj.com/doc/0813002581.html, P' U; A0 j6 ^. L( r6 d

指令序列; K* G. Y& S0 P; m

WEND

WHILE 、WEND 伪指令能根据条件的成立与否决定是否循环执行某个指令序列。当WHILE 后面的逻辑表达式为真,则执行指令序列,该指令序列执行完毕后,再判断逻辑表达式的值,若为真则继续执行,一直到逻辑表达式的值为假。

WHILE 、WEND 伪指令可以嵌套使用。" ^" o- z1 }* _0 G. f

使用示例:

GBLA Counter ;声明一个全局的数学变量,变量名为Counter CEDN论坛" W g/ h ]2 l) R

Counter SETA 3 ;由变量Counter 控制循环次数

…… 2 w1 v, /5 d9 A! z) Q/ a- F

WHILE Counter < 10 4 m# |2 o( o7 E" f/ k+ Q

指令序列0 n. {3 }9 ~- R% k' M. D

WEND

% Y [( v& o2 b# n& F

3、MACRO、MEND ( X6 l6 @ T/ O" O& M' V

语法格式:

$ 标号宏名$ 参数1 ,$ 参数2 ,……

指令序列% t: q' a+ u+ p9 W/ _8 G) e

MEND https://www.doczj.com/doc/0813002581.html,, Y4 d! T( I; }2 A* Z" p0 u

MACRO 、MEND 伪指令可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码。其中,$ 标号在宏指令被展开时,标号会被替换为用户定义的符号,宏指令可以使用一个或多个参数,当宏指令被展开时,这些参数被相应的值替换。' v: v( Z6 Y# D3 p

宏指令的使用方式和功能与子程序有些相似,子程序可以提供模块化的程序设计、节省存储空间并提高运行速度。但在使用子程序结构时需要保护现场,从而增加了系统的开销,因此,在代码较短且需要传递的参数较多时,可以使用宏指令代替子程序。

包含在MACRO 和MEND 之间的指令序列称为宏定义体,在宏定义体的第一行应声明宏的原型(包含宏名、所需的参数),然后就可以在汇编程序中通过宏名来调用该指令序列。在源程序被编译时,汇编器将宏调用展开,用宏定义中的指令序列代替程序中的宏调用,并将实际参数的值传递给宏定义中的形式参数。

MACRO 、MEND 伪指令可以嵌套使用。 3 U% u8 q& L' c

4、MEXIT https://www.doczj.com/doc/0813002581.html,9 s; n. T+ E7 O/ |: W2 }* V

语法格式:

MEXIT : K# N4 u4 h( Z- e7 u7 P* V

MEXIT 用于从宏定义中跳转出去。 3 U( N4 {5 z1 _1 T! v

https://www.doczj.com/doc/0813002581.html,: ^8 W* l; v& ?: T3 U. | _

其他常用的伪指令- G6 f- W6 _0 z

还有一些其他的伪指令,在汇编程序中经常会被使用,包括以下几条:

— AREA 0 j* p$ w) l) h6 S

— ALIGN

— CODE16 、CODE32 3 r$ A/ O$ p3 k( ~1 L) P

— ENTRY

— END

— EQU 8 M; N; m; d! H

— EXPORT (或GLOBAL )

— IMPORT

— EXTERN

— GET (或INCLUDE )

— INCBIN

— RN Y, @ G1 {% p% I& W

— ROUT

1、AREA 3 P0 W7 A& P2 D3 H

语法格式:9 N6 G: r) r6 _& i

AREA 段名属性1 ,属性2 ,……! w; i; ]# H1 v p- K

AREA 伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用“ | ”括起来,如|1_test| 。https://www.doczj.com/doc/0813002581.html,: Y n1 y% w/ ]( Y6 h9 t

属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:

— CODE 属性:用于定义代码段,默认为READONLY 。" ~% G- U3 l, o W% |3 G$ M6 f

— DATA 属性:用于定义数据段,默认为READWRITE 。CEDN论坛" U" X: j( e" r) j5 V+ u+ Q

— READONLY 属性:指定本段为只读,代码段默认为READONLY 。 4 N( M! s5 S/ T6 m! j

— READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。

https://www.doczj.com/doc/0813002581.html,1 O* t6 K9 ^0 Z+ c1 Y+ D

— ALIGN 属性:使用方式为ALIGN 表达式。在默认时,ELF (可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0 ~31 ,相应的对齐方式为2 表达式次方。

— COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON 段共享同一段存储单元。

一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。

使用示例:- r" S4 h5 y% Y

AREA Init ,CODE ,READONLY

该伪指令定义了一个代码段,段名为Init ,属性为只读

0 v% B8 U. U7 g8 m

2、ALIGN

语法格式:

ALIGN { 表达式{ ,偏移量}} $ t9 @) A8 g& P

ALIGN 伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式| 。其中,表达式的值用于指定对齐方式,可能的取值为2 的幂,如1 、 2 、 4 、8 、16 等。若未指定表达式,则将当前位置对齐到下一个字的位置。偏移量也为一个数字表达式,若使用该字段,则当前位置的对齐方式为:2 的表达式次幂+偏移量。

使用示例:https://www.doczj.com/doc/0813002581.html,& k9 f- k+ k5 A6 k( A

AREA Init ,CODE ,READONLY ,ALIEN =3 ;指定后面的指令为8 字节对齐。CEDN论坛* m3 k: s( l* {* R

指令序列, u( s" i1 /' m; g* N H- @

END

& }4 g& I. d2 K8 a

3、CODE16、CODE32

语法格式:

CODE16 (或CODE32 )' D( b* e) V& k3 b# m9 P$ J: o# O

CODE16 伪指令通知编译器,其后的指令序列为16 位的Thumb 指令。

CODE32 伪指令通知编译器,其后的指令序列为32 位的ARM 指令。CEDN论坛4 H% j$ P! O X- y7 u1 /" P

若在汇编源程序中同时包含ARM 指令和Thumb 指令时,可用CODE16 伪指令通知编译器其后的指令序列为16 位的Thumb 指令,CODE32 伪指令通知编译器其后的指令序列为32 位的ARM 指令。因此,在使用ARM 指令和Thumb 指令混合编程的代码里,可用这两条伪指令进行切换,但注意他们只通知编译器其后指令的类型,并不能对处理器进行状态的切换。https://www.doczj.com/doc/0813002581.html,9 T0 ]+ w6 B+ /; O: H! t

使用示例:

AREA Init ,CODE ,READONLY

……

CODE32 ;通知编译器其后的指令为32 位的ARM 指令

LDR R0 ,=NEXT +1 ;将跳转地址放入寄存器R0 - c1 {7 m0 G4 t. K1 O' x

BX R0 ;程序跳转到新的位置执行,并将处理器切换到Thumb 工作状态

……

CODE16 ;通知编译器其后的指令为16 位的Thumb 指令

NEXT LDR R3,=0x3FF

…… 6 E& c8 f& p- z' m) x9 t# T# r

END ;程序结束

https://www.doczj.com/doc/0813002581.html,+ h( P! A0 c3 q- b0 Q

4、ENTRY

语法格式:

ENTRY + R: z: ~5 y |5 @8 i/ h5 a6 G

ENTRY 伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个ENTRY (也可以有多个,当有多个ENTRY 时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个ENTRY (可以没有)。https://www.doczj.com/doc/0813002581.html,- O5 c n1 S2 D- A

使用示例:

AREA Init ,CODE ,READONLY https://www.doczj.com/doc/0813002581.html,4 R) ~" _. j* y+ v' |6 {- y! O& j

ENTRY ;指定应用程序的入口点CEDN论坛( o, n0 b# {: o% i+ Z6 g4 j

……- L' [8 @7 w" H$ v) @! e0 @- B

5、END

语法格式:

END

END 伪指令用于通知编译器已经到了源程序的结尾。CEDN论坛3 v" @5 a, F3 e9 N' f D$ d

使用示例:https://www.doczj.com/doc/0813002581.html,# a3 y& b7 |- s1 M2 c

AREA Init ,CODE ,READONLY

……7 p6 /) Z) `/ K k

END ;指定应用程序的结尾n% F" n* r1 _& K4 W. }6 V) Y8 H

6、EQU

语法格式:- O, x7 s) d- S1 G2 U2 B- j2 Q& w$ }

名称EQU 表达式{ ,类型}

EQU 伪指令用于为程序中的常量、标号等定义一个等效的字符名称,类似于C 语言中的#define 。

其中EQU 可用“ * ”代替。

名称为EQU 伪指令定义的字符名称,当表达式为32 位的常量时,可以指定表达式的数据类型,可以有以下三种类型:

CODE16 、CODE32 和DATA CEDN论坛, k6 /; K2 H1 t Y0 i/ ]* S

使用示例:; Q' ?+ |& y: O3 ]

Test EQU 50 ;定义标号Test 的值为50 - q& F8 /; K& j5 F5 E0 e

Addr EQU 0x55 ,CODE32 ;定义Addr 的值为0x55 ,且该处为32 位的ARM 指令。( t! v7 E6 g& ?* a5 G L3 W( u6 K& t3 E

/ g8 j* ^7 b& l0 ^8 E) H' B

7、EXPORT(或GLOBAL)7 ?+ ?0 l1 s7 Q1 _

语法格式:

EXPORT 标号{[WEAK]}

EXPORT 伪指令用于在程序中声明一个全局的标号,该标号可在其他的文件中引用。EXPORT可用GLOBAL 代替。标号在程序中区分大小写,[WEAK] 选项声明其他的同名标号优先于该标号被引用。

使用示例:https://www.doczj.com/doc/0813002581.html,' z$ t8 e) L/ P" Q' a2 V4 |

AREA Init ,CODE ,READONLY

EXPORT Stest ;声明一个可全局引用的标号Stest……

END

6 x

7 S, O% A0 e( C

8、IMPORT # |4 F0 w/ Y) e0 e" f2 N

语法格式:) w+ s& N- v+ w2 D. Y

IMPORT 标号{[WEAK]}

IMPORT 伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中。" H" H) s" D1 r) }% D

标号在程序中区分大小写,[WEAK] 选项表示当所有的源文件都没有定义这样一个标号时,编译器也不给出错误信息,在多数情况下将该标号置为0 ,若该标号为B 或BL 指令引用,则将B 或BL指令置为NOP 操作。8 h% R0 c' _" W2 O5 E; N( @6 _使用示例:

AREA Init ,CODE ,READONLY https://www.doczj.com/doc/0813002581.html,' q1 L, q1 v5 E

IMPORT Main ;通知编译器当前文件要引用标号Main,但Main 在其他源文件中定义……' ~# c6 y+ K7 r& B5 F4 u5 b

END

CEDN论坛6 y8 h8 w s: v% O& K& ?5 Y* N2 u

9、EXTERN

语法格式:% p. j% R6 w9 /8 y8 g

EXTERN 标号{[WEAK]}

EXTERN 伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,如果当前源文件实际并未引用该标号,该标号就不会被加入到当前源文件的符号表中。标号在程序中区分大小写,[WEAK] 选项表示当所有的源文件都没有定义这样一个标号时,编译器也不给出错误信息,在多数情况下将该标号置为0 ,若该标号为B 或BL 指令引用,则将B 或BL指令置为NOP 操作。

使用示例:

AREA Init ,CODE ,READONLY

EXTERN Main ;通知编译器当前文件要引用标号Main,但Main 在其他源文件中定义…… 6 } p" t: w# Y# A

END 6 O9 }6 s' h* W

CEDN论坛O) V2 r3 L* |& R! c0 _5 i; @

10、GET(或INCLUDE)

语法格式:

GET 文件名https://www.doczj.com/doc/0813002581.html," ]( L8 w: C. }

GET 伪指令用于将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以使用INCLUDE 代替GET 。

汇编程序中常用的方法是在某源文件中定义一些宏指令,用EQU 定义常量的符号名称,用MAP和FIELD 定义结构化的数据类型,然后用GET 伪指令将这个源文件包含到其他的源文件中。使用方法与C 语言中的“ include ”相似。

GET 伪指令只能用于包含源文件,包含目标文件需要使用INCBIN 伪指令

使用示例:

AREA Init ,CODE ,READONLY : ~3 f' k# N: b9 _ q

GET a1.s ;通知编译器当前源文件包含源文件a1.s 5 c8 M( b- Y7 C- d2 I

GE T C:/a2.s ;通知编译器当前源文件包含源文件C:/ a2.s ……https://www.doczj.com/doc/0813002581.html,9 R0 Z) z$ Q- W, d/ b* {7 ~

END ! u% ]4 X, b9 f, Y" i. t% E

* f+ ^3 |6 N( p7 Y+ T! ?5 D

11、INCBIN https://www.doczj.com/doc/0813002581.html,3 j; o1 E, a' v% L; g7 W% w

语法格式:' i, l; w4 P2 w' `) b

INCBIN 文件名

INCBIN 伪指令用于将一个目标文件或数据文件包含到当前的源文件中,被包含的文件不作任何变动的存放在当前文件中,编译器从其后开始继续处理。+ L( Q5 Q4 ~ Y. s 使用示例:9 Y x4 ~, J8 b# /9 ~4 y3 M1 p

AREA Init ,CODE ,READONLY , Y1 |$ h, ^7 i8 `' D) g

INCBIN a1.dat ;通知编译器当前源文件包含文件a1.dat

INCBIN C:/a2.txt ;通知编译器当前源文件包含文件C:/a2.txt……

END

12、RN https://www.doczj.com/doc/0813002581.html,0 z+ u4 m& r2 @8 H( c& @

语法格式:- L8 m. X. P. n( ^

名称RN 表达式: l' a1 ^( C# Y' b$ C* h W

RN 伪指令用于给一个寄存器定义一个别名。采用这种方式可以方便程序员记忆该寄存器的功能。其中,名称为给寄存器定义的别名,表达式为寄存器的编码。' @6 C3 u3 S! z" I* M ~7 @

使用示例:+ W4 x2 Q! G$ [7 M- e2 ^# O8 }

Temp RN R0 ;将R0 定义一个别名Temp ' /2 l c" J- F& [9 ], }# ]

CEDN论坛) K H% R- j+ @; w& w+ U5 @4 N. c

13、ROUT

语法格式:

{ 名称} ROUT

ROUT 伪指令用于给一个局部变量定义作用范围。在程序中未使用该伪指令时,局部变量的作用范围为所在的AREA ,而使用ROUT 后,局部变量的作为范围为当前ROUT 和下一个ROUT 之间。

ARM伪指令详述

1、AREA 语法格式: AREA 段名属性1,属性2,…… AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用―|‖括起来,如|1_test|。 属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:— CODE属性:用于定义代码段,默认为READONL Y。 — DATA属性:用于定义数据段,默认为READWRITE。 — READONL Y属性:指定本段为只读,代码段默认为READONL Y。 — READWRITE属性:指定本段为可读可写,数据段的默认属性为READWRITE。—ALIGN属性:使用方式为ALIGN 表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。—COMMON属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。 一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。 使用示例: AREA Init,CODE,READONL Y 指令序列 ;该伪指令定义了一个代码段,段名为Init,属性为只读 2、ALIGN 语法格式: ALIGN {表达式{,偏移量}} ALIGN伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式|。其中,表达式的值用于指定对齐方式,可能的取值为2的幂,如1、2、4、8、16等。若未指定表达式,则将当前位置对齐到下一个字的位置。偏移量也为一个数字表达式,若使用该字段,则当前位置的对齐方式为:2的表达式次幂+偏移量。 使用示例: AREA Init,CODE,READONL Y,ALIEN=3 ;指定后面的指令为8字节对齐。 指令序列 END 3、CODE16、CODE32 语法格式: CODE16(或CODE32) CODE16伪指令通知编译器,其后的指令序列为16位的Thumb指令。 CODE32伪指令通知编译器,其后的指令序列为32位的ARM指令。 若在汇编源程序中同时包含ARM指令和Thumb指令时,可用CODE16伪指令通知编译器其后的指令序列为16位的Thumb指令,CODE32 伪指令通知编译器其后的指令序列为32位的ARM指令。因此,在使用ARM指令和Thumb指令混合编程的代码里,可用这两条伪指令进行切换,但注意他们只通知编译器其后指令的类型,并不能对处理器进行状态的切换。使用示例: AREA Init,CODE,READONL Y …… CODE32 ;通知编译器其后的指令为32位的ARM指令

ARM的汇编指令讲解

汇编知识点的要求: 1、能看的懂 2、可以做修改 3、不需要用汇编直接编写程序 汇编代码的应用场合: 1、ARM的启动代码必须要汇编,如:uboot最开始初始化硬件的代码 2、内核在最开始初始化的位置。。。。 一、ARM汇编指令的编码格式 1、编码格式 ARM汇编指令编译成机器码以后,机器码的长度是32bits,这32bits的编码有一个固定的格式。不同ARM 汇编指令,编码格式不同。 2、举例 C: if(a==10) a++; else a--;

汇编1: CMP R0, #10; ADDEQ R0,R0,#1 SUBNE R0,R0,#1 汇编2 SUBS R1, R0, #10; //S ---运算的结果会影响条件码标志位:CPSR:NZCV ADDEQ R0,R0,#1 SUBNE R0,R0,#1 提示: 空指令NOP,实际上是占用CPU的时间,但是执行后,没有什么意义。 NOP ---- MOV R0,R0 3、条件码标识 10 -10 Z = 1 C = 0 N = 0 V = 0 ================================================================================= 二、ARM的寻址方式 1、立即数寻址 操作数,有立即数。 ADD R0,R0,#1

MOV R1,#10 ORR R1,R1,#0xf @ R1=R1 | 0xf BIC R1,R1,#0xf @R1 = R1&(~(0xf)) 错误: ADD R1,#1,#2 注意:立即数合法的条件 在ARM汇编指令中,并不是所有的立即数,立即数是有一定的限制的。 什么样的立即数是合法的??? 1、如果一个立即数是小于256的(即该立即数是8bits以内的,0~255),该立即数是合法的。 2、如果一个立即数是大于等于256,该立即数经过循环左移偶数位,可以得到一个小于256的数,则该立即数合法。 256 = 0x100 ------→左移20位0x10000000----→左移4 0x1 合法 0x111 非法 0x102 非法 0x104 合法 0xfff 0xff00 0x12000 0x450000 0xab 原因: 在数据处理指令编码的时候,立即数用12bits来表示: 高4bits:循环左移左移偶数位除以2 低8bits:循环左移后的结果。 重要问题: ADD R1,R0,#0xffff 非法 解决: LDR R2,=0xffff // R2=0xffff,将立即数0xffff的值传送给R2 ADD R1, R0, R2 2、寄存器寻址 所有的操作数都是寄存器,没有立即数 ADD R0,R0,R1 MOV R1,R0 ORR R1,R1,R0 @ R1=R1 | 0xf BIC R1,R1,R0 @R1 = R1&(~(0xf))

ARM汇编语言源程序格式

ARM汇编语言源程序格式ARM汇编语言源程序格式2010-11-16 13:52 来源:MCU嵌入式领域 常用ARM源程序文件类型 汇编语言程序的结构1 汇编语言程序的结构2 汇编语言程序的结构3 汇编语言程序的结构4 ARM的汇编语言程序一般由几个段组成,每个段均由AREA伪操作定义。 段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,如代码段的默认属性为READONLY,数据段的默认属性为READWRITE。 本程序定义了两个段,第一个段为代码段codesec,它在存储器中存放用于程序执行的代码以及main函数的本地字符串;第二个段为数据段constdatasec,存放了全局的字符串,由于本程序没有对数据进行写操作,该数据段定义属性为READONLY。 汇编语言的行构成1 格式: [标签]指令/伪操作/伪指令操作数[;语句的注释] 所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C 语言中的标签一样加上":";

ARM汇编器对标识符的大小写敏感,书写标号及指令时字母的大小写要一致; 注释使用";"符号,注释的内容从";"开始到该行的结尾结束 汇编语言的行构成2 标签 标签是一个符号,可以代表指令的地址、变量、数据的地址和常量。 一般以字母开头,由字母、数字、下划线组成。 当符号代表地址时又称标号,可以以数字开头,其作用范围为当前段或者在下一个ROUT伪操作之前。 指令/伪操作 指令/伪操作是指令的助记符或者定义符,它告诉ARM的处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。 汇编语言的标号1 标号代表地址。 标号分为段内标号和段外标号。段内标号的地址值在汇编时确定,段外编号的地址值在链接时确定。 在程序段中,标号代表其所在位置与段首地址的偏移量。根据程序计数器(PC)和偏移量计算地址即程序相对寻址。 在映像中定义的标号代表标号到映像首地址的偏移量。映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址即寄存器相对寻址。 例如:

伪指令

A51汇编解释---伪指令 2011-05-11 17:51:46| 分类:默认分类| 标签: |举报 |字号大 中 小订阅 一:定义符号的伪指令 1)SEGMENT 格式: 段名符号 SEGMENT 段类型 [再定位类型] SEGMENT指令可声明一个可再定位(区别于CSEG,DSEG,XSEG,BSEG,ISEG等定义的在相对应的空间固定地址定义的绝对段—在连接的过程中不允许重新定位)的段符号和一个可选的再定位类型,段符号可以用来定义段,L51连接器可将多个模块内的具有相同段名和再定位类型的几个段合成为一个段.段类型说明了段所处的地址空间. 如果是编写的汇编程序要与C源程序接口,即被C源程序调用,则全部的汇编子程序所命名的定义的代码段的段名必须是可用SEGMENT来定义的,而且名字的命名的方法也应该参照C51编译器产生的局部段的段名的转换规则.段名的作用主要是在汇编的时候用RSEG来激活的,在连接定位的时候用到的.与段名相应的是用于存储和传递参数的别名,可以在汇编源程序中直接应用局部段的别名,这个别名主要是在传递函数参数的时候用的.在汇编程序中要用PUBLIC 声明被其他模块引用的全局符号. DATA (可直接寻址的内部RAM空间) IDATA (可间接寻址的内部RAM空间) XDATA (外部数据存储空间) BIT (内部RAM低地址区的可位寻址的空间) CODE (程序存储器空间) 可选的再定位类型定义了L51连接时的定位方式,再定位类型: UNIT:定义一个可开始于任一单元的段对于BIT型的段,一个单元是一个位, 其它所有的段一个单元是一个字节. PAGE:定义一个起始地址必须是256的整数倍的段,段的绝对地址由L51自己计算,该类型只允许用于XDATA和CODE类型段. INPAGE:定义一个由L51连接后必须包含在256B的块中,只适用于XDATA和CODE段. INBLOCK:定义一个L51连接后必须包含在2KB中的段,只适用于CODE段. OVERLAYABLE:定义一个可与其他段交叠的覆盖段,其段名符号必须按C51或者PL/M51的规则命名.C51把局部数据段和局部位段定义成?DT?FUNCTIONNAME?MODULENAME 和?BI?FUNCTIONNAME?MODULENAME这是在small模式下.其他的模式略有不同。BITADDRESSABLE:定义一个L51连接后位于可位寻址的区,段长不能超过16B. 2) EQU 格式: 符号名 EQU 表达式 符号名 EQU 寄存器名 EQU伪指令定义一表示数值或寄存器的符号,该符号可用于表达式或助记符指令的操作数,EQU指令定义的符号不能被改变或重新定义,其段类型取决于表达式中的操作数类型类型,无类型的EQU符号可用于任何表达式中. LIMIT EQU 200 VALUE EQU LIMIT-100+’A’

ARM汇编伪指令宏的用法详解_MACRO-MEND_.

ARM 汇编伪指令宏的用法详解(MACRO-MEND 宏是一段独立的程序代码,它是通过伪指令定义的,在程序中使用宏指令即可调用宏。当程序被汇编时,汇编程序将对每个调用进行展开,用宏定义取代源程序中的宏指令。 MACRO 、MEND 语法格式: MACRO [$ label] macroname{ $ parameter1, $ parameter,…… } 指令序列 MEND MACRO 伪操作标识宏定义的开始,MEND 标识宏定义的结束。用MACRO 及MEND 定义一段代码,称为宏定义体,这样在程序中就可以通过宏指令多次调用该代码段。 其中, $ label在宏指令被展开时,label 会被替换成相应的符号,通常是一个标号。在一个符号前使用$表示程序被汇编时将使用相应的值来替代$后的符号。 macroname 为所定义的宏的名称。 $parameter为宏指令的参数。当宏指令被展开时将被替换成相应的值,类似于函数中的形式参数,可以在宏定义时为参数指定相应的默认值。 宏指令的使用方式和功能与子程序有些相似,子程序可以提供模块化的程序设计、节省存储空间并提高运行速度。但在使用子程序结构时需要保护现场,从而增加了系统的开销,因此,在代码较短且需要传递的参数较多时,可以使用宏汇编技术。首先使用MACRO 和MEND 等伪操作定义宏。包含在 MACRO 和 MEND 之

间的代码段称为宏定义体,在MACRO 伪操作之后的一行声明宏的原型(包含宏名、所需的参数),然后就可以在汇编程序中通过宏名来调用它。在源程序被汇编时,汇编器将宏调用展开,用宏定义体代替源程序中的宏定义的名称,并用实际参数值代替宏定义时的形式参数。 宏定义中的$label是一个可选参数。当宏定义体中用到多个标号时,可以使用类似$label.$internallabel的标号命名规则使程序易读。 MACRO 、 MEND 伪操作可以嵌套使用。 使用示例: MACRO $HandlerLabel HANDLER $HandleLabel ;宏的名称为HANDLER ,有1个参数$HandleLabel $HandlerLabel sub sp,sp,#4 stmfd sp!,{r0} ;decrement sp(to store jump address ;PUSH the work register to stack(lr does not push because it return to original address ;load the address of HandleXXX to r0 ;load the contents(service routine start address of HandleXXX ;store the contents(ISR of HandleXXX to stack ;POP the work register and pc(jump to ISR ldr r0,=$HandleLabel ldr r0,[r0] str r0,[sp,#4] ldmfd sp!,{r0,pc} MEND ;在程序中调用该宏

ARM常用的伪指令

在线学习好工作https://www.doczj.com/doc/0813002581.html,/ ARM常用的伪指令 AREA就是常见的伪指令之一。AREA是声明区域段,数据区,代码区等等。什么是数据段呢?数据段是来定义数据结构体的。格式是AREA test,CODE,READONLY。还有指令CODE16、CODE32,格式就直接写上就是。目的是声明以下是32位还是16位指令,注意不是切换arm和thunmb模式。如果是16位,那就是thunmb指令。 操作:这是之前的,如果在这里做一个声明,CODE32,也就是表示ARM指令。如果这里CODE16,就表示一下代码是16位指令,也就是thunmb指令, 也就是说在编译的时候会按照thunmb指令来进行汇编。大家注意一点,在这里通过这个切换,并不会改变处理器的运行的处理模式。不会把ARM指令状态切换为thunmb指令状态。这个切换是在状态寄存器里面去切换T。这个地方只是告诉汇编器而已,所以并不会更换运行时候的指令切换方式。 entry:entry伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要一个entry(也可以多个,当有多个entry时,程序的真正入口点由链接器指定),但在一源文件里最多只能有一个entry(可以没有)。 END:END伪指令用于通知编译器已经到了源程序的结尾。 EQU:EQU伪指令用于为程序中的常量、标号等定义一个等效的字符名称,类似于c语言的#define。格式是UARTLCON0EQU.0x3FFD00。比方说:SUNDYCON1

EQU0x3200000,我们定义了一个常量,这个常量可以拿来直接用。这里注意一点,我们编译先看一下。这里就出错了。 未知的操作代码。这是怎么回事?汇编这一块,跟自己的汇编器,编译器是有关系的,有时跟ID的环境都有关。在ARM里面,特别ADS里面,他对是否顶头,和Tab要求非常严格。因为我们这里不是一个标准指令,它会看第一个是什么操作码,这里操作码是不识别的,所以这里就出错认不出来。这是应该怎样做呢?首先把SUNDY顶头,就可以知道只是个伪指令。 EXPOET:export伪指令用于程序中声明一个全局的标号,该标号可在其他的文件中引用。export可用GLOBAL代替。标号在程序中区分大小写,weak选项声明其他的同名标号优先于该标号被引用。 IMPORT相当于静态引用。IMPORT伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号都会被加入到当前源文件的符号表中。 EXTERN相当于动态引用。EXTERN伪指令用于通知编译器要使用的标号在其他的源文件中定义,但要在当前的源文件中引用,如果当前源文件实际未引用该标号,该标号就不会被加到当前源文件的符号表中。 GET相当于引用文件。GET伪指令用于将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理。可以使用INCLUDE代替GET。 RN:RN伪指令用于给一个寄存器定义一个别名。采用这种方式可以方便程序员记忆该寄存器的功能。其中,名称为给寄存器定义的别名,表达式为寄存器的编码。

ARM汇编指令 对比记忆 (整理)

参考资料: 1. Richard Blum,Professional Assembly Language 2. GNU ARM 汇编快速入门,https://www.doczj.com/doc/0813002581.html,/u/31996/showart.php?id=326146 3. ARM GNU 汇编伪指令简介,https://www.doczj.com/doc/0813002581.html,/jb8164/archive/2008/01/22/41661.aspx 4. GNU汇编使用经验,https://www.doczj.com/doc/0813002581.html,/u1/37614/showart_39009 5.html 5. GNU的编译器和开发工具,https://www.doczj.com/doc/0813002581.html,/blog-htm-do-showone-uid-34335-itemid-81387-type-blog.html 6. 用GNU工具开发基于ARM的嵌入式系统,https://www.doczj.com/doc/0813002581.html,/liren0@126/blog/static/32897598200821211144696/ 7. objcopy命令介绍,https://www.doczj.com/doc/0813002581.html,/junhua198310/archive/2007/06/27/1669545.aspx 从网上找到一些关于ARM伪指令的资料,现整理如下: 一. Linux汇编行结构 任何汇编行都是如下结构: [:] [} @ comment [:] [} @ 注释 Linux ARM 汇编中,任何以冒号结尾的标识符都被认为是一个标号,而不一定非要在一行的开始。 【例1】定义一个"add"的函数,返回两个参数的和。 .section .text, “x” .global add @ give the symbol add external linkage add: ADD r0, r0, r1 @ add input arguments MOV pc, lr @ return from subroutine @ end of program 1. LDR LDR R0, =0X3FF5000 ;伪指令,把0X3FF5000这个地址送给R0 LDR R0, 0XFF ; 把立即数0xff送给R0 LDR R0, =&FF ; &相当于0X BIC R0, R0, #%1011 ;.#表示立即数,%表示二进制 LDR R1, =0x3ff5000 ;伪指令 R1=0X3FF5000 LDR R1, 0x3ff5000 ;存储器访问指令 R1= [0x3ff5000] 2. adr与ldr比较 adr r0, InitSystem ; ldr r1, =InitSystem ; 伪指令adr r0,InitSystem 编译时汇编成:sub r0,PC,#offset to InitSystem

ARM汇编伪指令介绍

ARM汇编伪指令介绍 在ARM汇编语言程序中,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊助记符为伪指令,它们所完成的操作称为微操作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。 在ARM 的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令及其它伪指令。 一、符号定义(Symbol Definition)伪指令 符号定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。 常见的符号定义伪指令有如下几种: —用于定义全局变量的GBLA、GBLL和GBLS。 —用于定义局部变量的LCLA、LCLL和LCLS。 —用于对变量赋值的SETA、SETL、SETS。 —为通用寄存器列表定义名称的RLIST。 1.GBLA、GBLL和GBLS 语法格式: GBLA(GBLL或GBLS)全局变量名 GBLA、GBLL和GBLS伪指令用于定义一个ARM程序中的全局变量,并将其初始化。 其中: GBLA伪指令用于定义一个全局的数字变量,并初始化为0; GBLL伪指令用于定义一个全局的逻辑变量,并初始化为F(假); GBLS伪指令用于定义一个全聚德字符串变量,并初始化为空; 由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。 使用示例: GBLA Test1:定义一个全局的数字变量,变量名为Test1 Test1 SETA 0xaa:将该变量赋值为0xaa GBLL Test2:定义一个全局的逻辑变量,变量名为Test2 Test2 SETL {TRUE};将该变量赋值为真 GBLS Test3:定义一个全局的字符串变量,变量名为Test3

arm汇编快速入门

ARM汇编语言 ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令作成. ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令. 伪操作,是ARM汇编语言程序里的一些特殊的指令助记符,其作用主要是为完成汇编程序做各种准备工作,在源程序运行汇编程序处理,而不是在计算机运行期间有机器执行.也就是说,这些伪操作只是汇编过程中起作用,一旦汇编结束,伪操作的使命也就随之消失. 宏指令,是一段独立的程序代码,可以插在程序中,它通过伪操作来定义,宏在被使用之前必须提前定义好,宏之间可以互相调用,也可自己递归调用.通过直接书写宏名来使用宏.并本具宏指令的格式输入输出参数.宏定义本身不产生代码,只是在调用它时把宏体插入到原程序中.宏与C语言中的子函数形参和实参的调用相似,调用宏时通过实际的指令来代替宏体实现相关的一段代码,但宏的调用与子程序的调用有本质的区别,既宏并不会节省程序的空间,其优点是简化程序代码,提高程序的可读性以及宏内容可以同步修改. 伪操作,宏指令一般与编译程序有关,因此ARM汇编语言的伪操作,宏指令在不同的编译环境下有不同的编写形式和规则. 伪指令也是ARM汇编语言程序里的特殊助记符,也不在处理器运行期间由机器执行,他们在汇编时将被合适的机器指令代替成ARM或Thumb指令,从而实现真正的指令操作. 目前常用的ARM编译环境有2种.

1. ADS/SDT IDE:ARM公司开发,使用了CodeWarrior公司的编译器. 2. 集成了GNU开发工具的IDE开发环境;它由GNU的汇编器as,交叉汇编器gcc和连接器id组成. ADS编译环境下的ARM伪操作和宏指令,可参考北航出版社的<

ARM伪指令

AREA伪指令 此伪指令用于给一段汇编代码或数据段起一个名字.一个完整的汇编程序至少要有一个以上的代码段,其语法格式为 AREA 段名属性1,属性2,.... 例: AREA init CODE,READONLY 定义了段名为init的属性为只读的代码. 其用意主要是当代码比较长时,可以根据功能来划分代码段,增加程序的可读性.所以段名的命名要符合该程序段的功能,换句话说也就是让人一看段名就知道该程序段是干什么用的. 2. EQU伪指令 EQU(equal 相等的意思,EUQ两边具有等价关系,通俗的说就是给一个表达式,为什么要给表达式名字,一是表达式太长了不好记忆,二是该表达式用得比较多,方便修改.想当与C语言里的符号常量.语法格式: 名字 EQU 表达式 ;表达式可以是常量 例: Number EQU 50 实际上我们在ARM里用得比较多的是: GPFCON EUQ 0x56000050 因为寄存器名和其对应的地址都是系统设计好了的.所以在这里几是想当与将寄存器名和它对应的地址之间的关系建立起来.这样就可以直接通过寄存器名来访问该寄存器了. 3 EXPORT伪指令 在程序里我们常常要定义很多标号,但那些标号只能在本文件中使用,通常一个工程包含很多个文件,要想在别的文件中使用该文件定义的标号就必须使用EXPORT伪指令.含义就是定义一个全局标号,语法格式: EXPORT 标号 例: EXPORT LOOP1

4 IMPORT伪指令 语法格式为: IMPORT 标号 起含义通知编译器此标号在别的文件定义,但在此文件中要使用.一个比较常用的用法是在汇编语言调用C函数时: AREA Init,CODE,READONLY IMPORT Main ;通知编译器当前文件要引用标号Main,但Main在其他源文件中定义 镲 END 5 GET伪指令 相当C语言的INCLUDE指令,语法格式为: GET 文件名 例:GET a1.s ;通知编译器源文件a1.s被包含当前源文件. 作用用于将一个源文件包含到当前的源文件中,并将被包含的源文件在当前位置进行汇编处理,但注意GET伪指令只能用于包含源文件,包含目标文件需要使用INCBIN. 伪指令 6 INCBIN INCBIN伪指令用于将一个目标文件或数据文件包含到当前的源文件中,被包含的文件不作任何变动的存放在当前文件中,编译器从其后开始继续处理 语法格式: INCBIN 文件名 INCBIN a1.dat ;通知编译器当前源文件包含文件a1.dat

(完整版)汇编语言中常用的伪指令档

汇编语言中常用的伪指令 分类:软件相关2013-01-23 20:13 515人阅读评论(0) 收藏举报areaequ伪指令常用汇编语言 汇编语言中,指令语句在源程序汇编时会产生可供计算机执行的指令代码,即目标代码。汇编程序除指令语句外,还需要提供一些指令,用于辅助源程序的汇编。比如指定程序或数据存放的起始地址,为数据分配一段连续的内存单元等。这些指令在汇编时并不生成目标代码,不影响程序执行,因此称之为伪指令。本文简单总结了常用的伪指令,如下。 1、EQU(Equate) 一般格式为:标号:EQU 操作数 指令功能为将操作数赋予标号,两边的值完全相等。使用EQU伪指令给一个标号赋值后,此标号在整个源文件中值固定。 AREA: EQU 1000H ;将标号AREA赋值为1000H 2、ORG(Origin) 一般格式为:ORG xxxxH(绝对地址或标号) XxxxH决定此语句后第一条指令(或数据)的地址。该段源程序或数据被连续存放在此后的地址内,直到下一条ORG指令为止。 ORG 8000H ;此后目标代码存储在存储器中以0x8000h开始的地址空间中。 ADD R1,#1 MOV R2, #2 3、DB(Define Byte) 一般格式为:标号:DB 字节常数或字符或表达式 标号字段可有可无,字节常数或字符是指一个字节数据。此伪指令的功能是把字节常数或字节串存放至内存连续的地址空间中。 ORG 8000H DATA1:DB 43H,09H,08H DATA2:DB 07H 伪指令DB指定了43H,09H,08H 顺序存放在8000H开始的存储单元中,DATA2中的07H紧挨着DATA1的地址空间存放,即07H存放在8003H单元中。 注:DW(Define Word)指令定义与DB类似,区别在于DW定义一个字,DB定义一个字节。

ARM汇编实验报告

《嵌入式系统原理与应用B》课程实验报告 ARM汇编语言编程与调试 要求完成的主要实验 1、给出的数据中寻找最大、最小数问题 2、两种求和运算的编程与调试 3、第四章作业第9题 4、排序冒泡程序的调试与总结 5、第四章作业第11题 说明:标注完成的实验,未完成的给予说明 专业名称:通信工程 班级:1510班 学生姓名:石龙飞 学号(8位):03151307 指导教师:刘钊远

给出的数据中寻找最大、最小数问题 一、实验目的 1、学习汇编软件的安装、使用,熟悉汇编环境。 2、学会使用汇编软件,如何新建一个工程,如何书写源代码,如何进行链接、编译,以及如何调试。 3、尝试一些简单的指令,学会用汇编指令写一些简单的程序。 二、实验内容 编写一个汇编程序,要求在给定的一组数中找到最大数和最小数。 三、实验主要步骤 1、首先建立一个工程 2、再新建.s的源文件,添加到工程中 3、编写源代码,这里主要是实现在一组数中寻找最大数和最小数,最后将找到的两个数放到相应的寄存器中。

4、进行链接编译,看看有没有语法的错误,如果有错误编译器会提示错误的类型以及在哪里出错。 5、进行debug调试,查找代码中的逻辑错误,若无逻辑错误,可在debug界面查看运行结果,其最需要的关注的几个地方是菜单栏的一组运行按钮、源码执行的步骤以及断点、左边的寄存器状态、下方的存储器状态,将这些综合起来,就可以很明确的回到程序如何运行,运行结果如何。

四、实验代码

五、实验总结与分析 1、实验结果分析 其中用红色方框框起来的是最后程序运行的结果,也就是在R3中保存了最小数在R2中保存了最大数,完成了实验要求。 2、在用汇编语言编程之前首先要看看有没有汇编软件ADS、没有的话需要安装,WindowsXP安装起来比较简单,只需要点击setup,一直点击写一部就可以,但是如果是Windows 7或者更高版本的话就需要在setup的属性里点击兼容WindowsXP,运行时以管理员身份运行才能正确进行安装。

ARM GNU 汇编伪指令简介,编译器和开发工具,用GNU工具开发基于ARM的嵌入式系统

ARM GNU 汇编伪指令简介 1 ARM GNU 汇编伪指令简介 (1)abort .abort 停止汇编 (2)align .align absexpr1,absexpr2 以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或 32. 第二个表达式值表示填充的值 (3)if...else...endif .if .else .endif: 支持条件预编译 (4)include .include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中 (5)comm .comm symbol, length: 在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length. Ld连接器在连接会为它留出空间 (6)data .data subsection: 说明接下来的定义归属于subsection数据段 (7)equ .equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间 (8)global .global symbol: 定义一个全局符号, 通常是为ld使用 (9)ascii .ascii "string": 定义一个字符串并为之分配空间 (10)byte .byte expressions: 定义一个字节, 并为之分配空间 (11)short

.short expressions: 定义一个短整型, 并为之分配空间 (12)int .int expressions: 定义一个整型,并为之分配空间 (13)long .long expressions: 定义一个长整型, 并为之分配空间 (14)word .word expressions: 定义一个字,并为之分配空间, 4 bytes (15)macro/endm .macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束, .exitm 跳出宏, 示例如下: .macro SHIFTLEFT a, b .if \b < 0 mov \a, \a, ASR #-\b .exitm .endif mov \a, \a, LSL #\b .endm (16)req name .req register name: 为寄存器定义一个别名 (17)code .code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令(18)ltorg .ltorg: 表示当前往下的定义在归于当前段,并为之分配空间 2 ARM GNU专有符号 (1)@ 表示注释从当前位置到行尾的字符. (2)# 注释掉一整行. (3); 新行分隔符. 3 操作码 (1)NOP: nop 空操作, 相当于MOV r0, r0

ARM复习课后题答案(完整版)

1.国内嵌入式系统行业对嵌入式系统的定义是什么?如何理解 答:以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 从这个定义看以看出嵌入式系统是与应用紧密结合的,它具有很强的专用性,必须结合实际系统要求进行合理的裁剪利用。因此有人把嵌入式系统比作是一个针对特定的应用而量身定做的专用计算机系统。 2.当前最常见的源码开放的嵌入式操作系统有哪些,请举出两例,并分析其特点 答:嵌入式linux和嵌入式实时操作系统uc/os-II Linux: (1)linux是源码开放的,每一个技术细节都是透明的,易于裁剪定制。 (2)目前嵌入式linux已经在多种嵌入式处理器芯片移植成功,有大量且不断增加的开发工具,这些工具为嵌入式系统开发提供了良好的开发环境。 (3)Linux内核小、功能强大、运作稳定、效率高。 Ucos: (1)源代码公开 (2)可移植性。 (3)可固化 (4)可裁剪 (5)占先式 (6)多任务 (7)可确定性。 (8)系统服务 第2章ARM技术与ARM体系结构 3.arm处理器的工作模式有哪几种,其中哪些为特权模式,哪些为异常模式,并指出处理 器在什么情况下进入相应的模式。 答:ARM 处理器共有7 种工作模式: 用户模式:非特权模式,也就是正常程序执行的模式,大部分任务在这种模式 下执行。在用户模式下,如果没异常发生,不允许应用程序自行改变处理器的工作 模式,如果有异常发生,处理器会自动切换工作模式 FIQ 模式:也称为快速中断模式,支持高速数据传输和通道处理,当一个高优 先级(fast)中断产生时将会进入这种模式。 IRQ 模式:也称为普通中断模式,:当一个低优先级中断产生时将会进入这种模 式。在这模式下按中断的处理器方式又分为向量中断和非向量中断两种。通常的中 断处理都在IRQ 模式下进行。 SVC 模式:称之为管理模式,它是一种操作系统保护模式。当复位或软中断指 令执行时处理器将进入这种模式。 中止模式:当存取异常时将会进入这种模式,用来处理存储器故障、实现虚拟 存储或存储保护。 未定义指令异常模式:当执行未定义指令时会进入这种模式,主要是用来处理 未定义的指令陷阱,支持硬件协处理器的软件仿真,因为未定义指令多发生在对协 处理器的操作上。 系统模式:使用和User 模式相同寄存器组的特权模式,用来运行特权级的操作

ARM汇编中关于“.word”伪指令的概念

PS:在u-boot源码时遇到_armboot_start、_bss_start等这些变量,不知道指向什么地址,于是查了一下,弄清了ARM汇编中“.word”这个伪指令是什么意思了,感觉自己很菜。借鉴一下网友帖子的内容,关键在帖子最后的总结: 汇编和C引用变量的不同:汇编是“绝对”引用,即没有指针的概念,引用得到的就是值;c语言是“间接”引用,相当于指针的概念,引用地址变量,得到的就是该变量所指的内容值。 感谢原作者,以下为原帖: aaronwong: u-boot中代码的疑问(_armboot_start与_start)? --------------------------- 我使用的是u-boot-1.3.0-rc2。在cpu/pxa/start.S中,有如下的标号定义: _TEXT_BASE: .word TEXT_BASE /*uboot映像在S DRAM中的重定位地址,我设置为0xa170 0000 */ .globl _armboot_start _armboot_start: .word _start /*_start是程序入口,链接完毕它的值应该是0xa170 0000=TEXT_BASE*/ /* 这句话的意思应该是在_armboot_start标号处,保存了_start的值,也就是说,_armboot_start 是存放_start的地址,该地址对应的存储单元内容是0xa170 0000*/ /* * These are defined in the board-specific linker script. 下面的定义与上面应该是一个意思。 */ .globl _bss_start _bss_start: .word __bss_start ====================== 按照上面的理解,__bss_start是uboot 的bss段起始地址,那么uboot映像的大小就是 __bss_start - _start;在relocate代码段中计算uboot的大小时,也体现了这一点。 实际上,_armboot_start并没有实际意义,它只是在"ldr r2, _armboot_start"中用來寻址_start 的值而已,_bss_start也是一样的道理,真正有意义的应该是_start和__bss_start本身。 但是,令我不解的是,在C入口函数start_armboot()中(对应文件为lib_arm/board.c),有如下代码: void start_armboot (void) { ......... gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); //第一句话.......... monitor_flash_len = _bss_start - _armboot_start; //第二句话............... mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); //第三句话 .......... } ============================================== 按照上面的理解,_armboot_start与_bss_start都是没有实际意义的,它们只是一个地址,有实

常用ARM及汇编指令

用ARM指令及汇编包括 (2) 指令集介绍 (4) ARM数据处理指令包括 (7) ARM伪指令介绍 (9) ARM汇编程序设计及一些格式要求说明 (13)

用ARM指令及汇编包括 1、ARM处理器寻址方式 2、指令集介绍 3、伪指令 4、ARM汇编程序设计 5、C与汇编混合编程 ARM处理器寻址方式 1、寄存器寻址:操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值操作 MOV R1, R2 ;R2->R1 SUB R0, R1,R2 ;R1-R2 -> R0 2、立即寻址:立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令就取出了可以立即使用的操作数SUBS R0,R0,#1 ;R0-1 -> R0 MOV R0,#0xff00 ;0xff00 -> R0 注:立即数要以"#"为前缀,表示16进制数值时以"0x"表示 3、寄存器偏移寻址:是ARM指令集特有的寻址方式,当第2操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前选择进行移位操作MOV R0,R2,LSL #3 ;R2的值左移3位,结果存入R0,即R0 = R2 * 8 ANDS R1,R1,R2,LSL R3 ;R2的值左移R3位,然后和R1相与操作,结果放入R1 寄存器偏移寻址可采用的移位操作如下 (1)、LSL(Logical Shift Left)逻辑左移,寄存器中字的低端空出补0 (2)、LSR(Logical Shift Right)逻辑右移,寄存器中字的高端空出补0 (3)、ASR(Arthmetic Shift Right)算术右移,移位中保持符号位不变,即如果源操作数为正数,字高端空出补0,否则补1 (4)、ROR(Rotate Right)循环右移,由字的低端移出的位填入高端空出的位 (5)、RRX(Rotate Right eXtended by 1 place),操作数右移一位,左侧空位由CPSR的C填充 4、寄存器间接寻址:寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需要的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针 LDR R1,[R2] ;将R2中的数值作为地址,取出此地址中的数据保存在R1中SWP R1,R1,[R2] ;将R2中的数值作为地址,取出此地址中的数值与R1中的值交换

ARM汇编语言编程详解

ARM汇编语言编程详解 硅谷芯微嵌入式学院技术贡献网址:https://www.doczj.com/doc/0813002581.html,

4.1 汇编语言 使用汇编语言编写程序,它的特点是程序执行速度快,程序代码生成量少,但汇编语言是一种不易学习的编程语言,并且可读性较差,这种语言属于低级语言。每一种汇编语言对应每一款芯片,使用这种语言需要对硬件有深刻的了解。在通常情况下,可以使用汇编语言编写驱动程序、需要严格计算执行时间的程序以及需要加速执行的程序。

先介绍一个例子来说明ARM汇编程序的格式。 例1 计算20+8,结果放入R0寄存器。 AREA Buf, DATA, READWRITE ;声明数据段Buf Count DCB 20 ;定义一个字节单元Count AREA Example, CODE, READONLY ;声明代码段Example ENTRY ;标识程序入口 CODE32 ;声明32位ARM指令START LDRB R0, Count ;R0 = Count =20 MOV R1, #8 ;R1 = 8 ADD R0, R0, R1 ;R0 = R0 + R1 B START END

例1中定义了两个段:数据段Buf和代码段Example 。数据段中定义了字节单元Count,其中Count用来保存一个被加数;代码段中包含了所有源程序代码,程序中首先读取Count字节单元的内容,然后与立即数8相加,计算结果保存到R0中。 由例1可见,ARM汇编语言的源程序是分段的,由若干个段组成一个源程序。源程序的一般格式为: AREA name1, attr ;声明特定的段标号语句1 ;语句 ... 语句n AREA name2, attr 标号语句n+1 ... 语句n+m END ;结束符

相关主题
文本预览
相关文档 最新文档