一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3814|回复: 0

GNU ARM汇编快速入门

[复制链接]
发表于 2016-12-18 16:23 | 显示全部楼层 |阅读模式
GNU ARM汇编快速入门
( {4 l5 ]9 m1 [; A" W- \' \* f/ M以前用ARM的IDE工具,使用的是ARM标准的汇编语言。现在要使用GNU的工具,当然要了解一点GNU ARM汇编的不同之处。其实非常的简单,浏览一下文档然后再看看程序就完全可以搞定了,或者你硬着头皮看GNU ARM的汇编程序,用不了多少时间你就就可以无师自通了。
* y, L! i' e* a  `' s4 E; S; s2 K
ARM汇编语言源程序语句 ,一般由指令、伪操作、宏指令和伪指令作成。ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令。 * ^/ b  j) t( I& n
+ ^% v& O/ t6 z1 g; W9 l
目前常用的ARM编译环境有2种:# @/ b  s# |% n! }% a3 t( O+ S
ARMASM: ARM公司的IDE中使用了CodeWarrior的编译器,绝大多数windows下的开发者都在使用这一环境,完全按照ARM的规定;
8 c7 a" c3 x+ X4 v& JGNU ARM ASM:GNU工具的ARM版本,与ARMASM略有不同; 1 ~: Y, ~/ \6 O+ K- x/ ]3 D
$ W* b: l* }- X0 D% I' [3 b
关于CodeWarriror ARM汇编的书和文章很多,本文假定你已经完全了解ARMASM,这里只说明GNU ARM汇编,并针对ARMASM给出说明。本文翻译自:GNU ARM Assembler Quick Reference, 本人水平有限,错误难免,转载随意,请注明出处。英文原文地址不详。
& \) X) D% U8 D5 U6 u' h6 i- c: a8 p7 |  B

; d# P/ e' ]" e. QGNU ARM 汇编快速入门
# W# y! H# ?5 X3 C( m1 `; p任何汇编行都是如下结构:: K7 h4 I+ u  Y7 m  A
[<label>:] [<instruction or directive>} @ comment
, P" u6 W  D- O[<标签>:] [<指令>} @ 注释
7 R4 b+ K7 q, n8 i* P; N, TGNU ARM 汇编中,任何以冒号结尾的都被认为是一个标签,而不一定非要在一行的开始。下面是一个简单的例子,这段汇编程序定义了一个"add"的函数,该函数返回两个参数的和:
# L7 n4 a: N+ w7 d% ~.section .text, “x”5 }9 A% f$ m% a# Z
.global add @ give the symbol add external linkage( U+ b) l9 B2 q- s" K. [. \
add:
" g1 Y+ q) ^1 O2 P" q2 ZADD r0, r0, r1 @ add input arguments7 |- m+ x# T1 n1 {3 x6 \% N0 T
MOV pc, lr @ return from subroutine: g" W4 y. g# s  e/ D
@ end of program
5 D+ z" A$ j$ a* F! k( JGNU ARM汇编伪指令
: s# \$ W/ l: F4 i; s
, h9 x- E+ E  c9 t- P4 D3 p. T下面列出了一些GNU ARM汇编伪指令,并给出了相应说明。- ]4 q% t  A$ V& U" R* n1 c

1 n4 z! v3 h8 L( S, Z( }8 ^: ?9 r  Q.ascii “<string>” 在汇编中定义字符串并为之分配存储空间(与armasm中的DCB功能类似)。 5 N1 s. x% y' X3 j1 Y* `% F
.asciz “<string>” 和.ascii类似, 但不分配存储空间。
9 |5 K- a" K: z9 p.balign <power_of_2> {,<fill_value> {,<max_padding>} } 3 t( U% @. w* w4 g
以某种排列方式在内存中填充数值。 (该指令与armasm中的ALIGN类似)。. D0 f3 V; ]- d* _2 c
power_of_2表示排列方式,其值可为4,8,16或32,单位是byte; " c: o: d$ t/ V  W8 k
fill_value是要填充的值;
! v1 y2 v# I, e6 t/ Fmax_padding最大的填充界限,请求填充的bytes数超过该值,将被忽略。* s- c7 w: i" }! M4 K% U; p4 \7 D
.byte <byte1> {,<byte2>} … 定义一个或多个Byte,并为之分配空间(与armasm的DCB类似)。  
' P* _8 n$ [$ u0 e4 J.code <number_of_bits> 设定指令宽度,16表示Thumb,32表示ARM assembly
* l* p9 m* J# m) c(和armasm中的CODE16,CODE32相同)。
" R5 p2 u( O/ R. D.if  
0 O1 ?% `& m( A.else # D+ M; R* H. u+ L1 t# F6 h
.endif % e: E# U" F4 U2 V3 ^# l9 h
预编译宏(与armasm中的IF ELSE ENDIF相同)。; ~" p& N! k) M0 y2 F3 E: ?' W
.end 汇编文件结束标志,常常省略不用。
) _8 m7 I# `7 a: j7 @) v- W& [0 H% i! C, Q5 p: N
.endm 宏结束标志。
# z* F" O$ C2 X/ w.exitm 宏跳出。
( t" }. J: G& ?4 }. ]6 s6 l- `( ?.macro <name> {<arg_1} {,<arg_2>} … {,<arg_N>}
: ~0 k. l* Y. U7 F' [定义一段名为name的宏,arg_xxx为参数。
) S% b( J  i* f. W% h/ Q! E7 l5 v必须有对应的.endm结尾。
" _3 g& j# Z% Q& N7 Y' t' _可以使用.exitm从中间跳出宏。(与armasm中的MACRO, MEND, MEXIT相同)。 7 R. e7 R% f& f1 J
在使用宏参数时必须这样使用:“\<arg>”。
2 m) k6 p/ B& y. _例如: 9 |* y) v5 G' v9 V& \2 f0 v% p
[CODE].macro SHIFTLEFT a, b9 N4 z/ B; P6 Z* R* F; ^
.if \b < 0
/ A9 _8 O: N4 ]MOV \a, \a, ASR #-\b7 u/ e$ i6 n$ o3 A, v1 e1 R" \
.exitm. N5 c; U1 e; I: o$ r: X
.endif
4 Z0 [6 m8 n5 rMOV \a, \a, LSL #\b
" A( |' p) Q5 `1 s* Q' E6 D" x.endm
' |, h, O  n% J, v/ ^) t3 O6 x8 I6 ]: R2 t" C' l
.rept <number_of_times> 循环执行.endr前的代码段number_of_times次。
( ~* T; ?+ [: i7 ^7 o! c2 X1 c(与armasm中的WEN相似), t; |" i. y2 U  e

# _- |4 X7 |- l: F6 p' _.irp <param> {,<val_1>} {,<val_2>} … 5 ^4 H+ P- m* \, Q& R2 g
循环执行.endr前的代码段,param依次取后面给出的值。: E$ C3 m% \( s% f
在循环执行的代码段中必须以“\<param> ”表示参数。+ [7 m2 E$ f/ U- o! v
) R2 Y3 s7 E, Q% C
.endr 结束循环(与armasm中的WEND相似).
! i: V6 S$ d$ ?0 x.equ <symbol name>, <value> 为一个标号赋值,类似C中的#define。(与armasm中的EQU相同)
7 O) e- ^$ g1 s* F- ~3 ^9 l9 I0 _.err 编译错误报告,将引起编译的终止。
" n" u& q9 B  q& u2 R8 j.global <symbol> 全局声明标志,这样声明的标号将可以被外部使用。(与armasm中的EXPORT相同)。
) W2 k  E. b1 F/ K.hword <short1> {,<short2>} …
! y: v8 {) G& }插入一个16-bit的数据队列。(与armasm中的DCW相同)$ D6 @2 o4 U7 b( B
.ifdef <symbol> 如果 <symbol>被定义,该快代码将被编译。以 .endif结束。7 C4 J3 d5 d2 z0 E& l7 T
.ifndef <symbol> 如果 <symbol>未被定义,该快代码将被编译。以 .endif结束。7 l' P' o* ~: U5 p
.include “<filename>” 包含文件。(与armasm中的INCLUDE 或者C中的#i nclude一样)
/ {) l$ L/ I' E' w$ `<register_name> .req <register_name>
2 l. P( t) S7 [/ P: h$ u' N$ z定义一个寄存器,.req的左边是定义的寄存器名,右边是使用的真正使用的寄存器。
  G9 t- N; \9 Y+ c1 }) D(与armasm中的RN类似)
; Y# I/ m: G* u9 x# P$ Q例如:acc .req r0  D+ e- R0 \# ?% M
[CODE].section <section_name> {,”<flags>”}- H) c& C: l- q) o7 }% O
开始一个新的代码或数据段。.text, 代码段;.data, 初始化数据段;.bss, 未初始化数据段。 " n9 Q$ t0 r) h% C1 z& g9 q3 ~; y1 f
这些段都有缺省的标志(flags),联接器可以识别这些标志。(与armasm中的AREA相同)。
3 o# G; r% K+ i$ `; t: ^5 Z下面是ELF格式允许的段标志. C8 M7 P: K2 R, A4 p. _
<标志> 含义
+ W7 w4 K* C7 m6 k; e) da 允许段% _1 Z$ X1 C* t5 c
w 可写段1 G4 U+ |% _4 [. O4 i
x 执行段
, c9 \- U- f8 A" N2 b* u9 ^.set <variable_name>, <variable_value> 变量赋值。(与armasm中的SETA相同)
6 W! w/ h2 o1 u/ @0 n.space <number_of_bytes> {,<fill_byte>}+ q; R5 O0 w8 e1 J: }4 j# R
分配number_of_bytes字节的数据空间,并填充其值为fill_byte,若未指定该值,缺省填充0。' b4 r) Y6 }1 i( Q6 c1 f
(与armasm中的SPACE功能相同)0 F6 t! J* C# k; |* y
.word <word1> {,<word2>} …
3 _; N  B5 n% c4 S, o1 k插入一个32-bit的数据队列。(与armasm中的DCD功能相同); }8 h" H) o0 r' ?1 t

9 q& T% O0 G/ o6 E+ {1 n0 ZGNU ARM汇编特殊字符和语法/ a3 o7 e# |4 Q6 x! r1 Q

) J& K3 J  ?, a2 {2 l3 h代码行中的注释符号: ‘@’
2 I7 _8 X1 C: n$ w* o1 R) S整行注释符号: ‘#’
3 ]  k  r2 E) a9 T' e5 R. M* t语句分离符号: ‘;’
; N9 s. N6 S0 a直接操作数前缀: ‘#’ 或 ‘$’8 F$ f! x4 h) P& M
.arm 以arm格式编译,同code32 " E( g( G4 C, V. G; I
.thumb 以thumb格式编译,同code16
8 }% {8 I0 V: B2 [) ~. ]! d) J) A.code16 以thumb格式编译
" b- {5 l$ u+ v& {5 u0 ^1 }# ~.code32 以arm格式编译
6 _  l/ O: g0 H; H7 b) U" \- _篇后语:6 e! D8 m& ^! l
- _, c3 q8 S& n" P
更详细的使用说明请参照:ARM Architecture Reference Manual, Addison-Wesley ISBN 0-201-73719-1  E- _3 A! q% t4 v2 u
补充:
5 G6 D8 O  y' b& _1 O7 o1 L
) t3 [& F8 F: U# I; B4 ARM GNU常用汇编语言介绍6 q+ `# x) o3 n
4.1 ARM GNU常用汇编伪指令介绍
) t. l5 y% f7 n7 H1. abort
- L/ q; N# k/ M. v.abort: 停止汇编$ a# N! v3 m- x4 ?9 Z
.align abs-expr1, abs-expr2: 以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第" v( I* A4 U6 `
二个表达式值表示填充的值.
5 Q; ?: S4 f! N/ A2. if...else...endif
# s9 w9 ?; ^* y$ J7 w.if/ |* V# m9 \0 a9 N, A) S
.else
7 ^7 B  m+ Q! S( X.endif: 支持条件预编译' J8 U) u; x7 v  F8 C$ @1 C. u
3. include
" w" \, z' [7 W) g# c& c" }; w.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中.
% z5 U2 i0 a0 a. b$ F1 ^& Y4. comm
" v. [; i# g# i# N/ q.comm symbol, length:在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length.      Ld连接器在连接会- K- ?9 u) a6 \4 C8 m- X
为它留出空间.. Y" M, G) i1 q7 d4 T+ K8 q
5. data$ O- v& b1 q. ^, @. A4 \
.data subsection: 说明接下来的定义归属于subsection数据段." [7 R3 h2 G$ a* a+ w$ h
6.      equ) Z" x9 ~& ~0 A. o: {2 L0 Q
.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.
, v8 l8 h2 y6 c9 a6 j7. global, [0 s, U- v' `7 H
.global symbol: 定义一个全局符号, 通常是为ld使用.
- z  ?9 v6 l2 L: c/ `2 I8. ascii: K/ L2 G: o; L. Z
.ascii "string": 定义一个字符串并为之分配空间.
9 G6 \  j- V2 }$ h9. byte3 A. A5 E6 F% j" P) z1 G
.byte expressions: 定义一个字节, 并为之分配空间.3 B; S8 e9 h! Y
10. short; @( m4 i3 ~" X% K* I1 A) s
.short expressions: 定义一个短整型,      并为之分配空间.$ p/ k3 ?$ |% ]. S3 V- ~
11. int
$ Z3 }+ f& }7 ]% @" h.int expressions: 定义一个整型,并为之分配空间.
" z) ]; A3 p3 I% G$ U" Z12 long
4 f" t5 A1 x- Z# T.long expressions: 定义一个长整型, 并为之分配空间.( v, m( H4 R1 ~# e
13 word
7 d9 Q( A( n3 D.word expressions: 定义一个字,并为之分配空间, 4bytes.& m1 z. N( A5 b: d' q: z8 i
14. macro/endm
+ o7 ]  R2 P, ^1 h) P# a/ i! k/ G* f.macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束.0 `' D- a& X/ Z* N' r
15. req5 J+ R) ?+ s5 G% m2 E* l* `
name .req register name:      为寄存器定义一个别名.
, \9 v' p+ s& h16. code
; \- O: Y$ m: g1 R9 G. [.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令.+ ]/ ^% I* Y- k- {+ C
17. ltorg2 c; W. @$ l. H6 R7 F  K8 W
.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间.5 ]- n& {  V; |/ N5 ?% k! U
4.2 ARM GNU专有符号& n3 L0 m6 i7 N8 h2 y' {
1. @
% [$ O; M+ Z/ s& p表示注释从当前位置到行尾的字符./ V6 C$ d' i9 m2 r
2. #
2 i" j: r# \3 n$ w' a; q* Y! }: l注释掉一整行./ L2 L, E7 k/ y  f5 C& U& o6 j. g
3. ;
0 R& T; ~: U: F' i; _新行分隔符.
* Q# y" L$ i4 U4.3 操作码6 a4 {% q9 [4 G0 j3 H  r3 [5 O
1. NOP
# P) B% t# ]2 M" Y- N% j" s: ~- B       nop& y& s; `0 i  F; i" i, {
       空操作, 相当于MOV r0, r0) s" X0 b, o# T( T1 J
2. LDR
4 Z8 f. ^# R' p4 C9 l$ `1 @  K          ldr <register> , = <expression>5 E# ?* D+ j! I
       相当于PC寄存器或其它寄存器的长转移.6 ^2 Y) j2 _2 n7 W* Y7 w- W
3.ADR
5 W3 O* m; E% c# n          adr <register> <label>/ U! W% `% x' ^" c; J& a/ W
       相于PC寄存器或其它寄存器的小范围转移.1 q& N. n; _1 z
       ADRL
' ~* g3 Z0 B! C* V          adrl <register> <label>
9 C2 ^8 u7 u! s       相于PC寄存器或其寄存器的中范围转移.
& r- X/ U, r1 U1 M( a
8 O0 D# d# Y) B* M5 A$ K9 N, Q原文地址:http://blog.csdn.net/lbsljn/archive/2009/06/17/4277640.aspx* s8 r; S( p  ^* s- M! b8 R) e

2 n+ ^# S& D, u6 o- H9 O" ~

) L6 R$ w: K# j0 v9 j
8 c! D2 @# u( `, {* ^) [

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2026-4-17 16:28 , Processed in 0.029171 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表