一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3644|回复: 0

GNU ARM汇编快速入门

[复制链接]
发表于 2016-12-18 16:23 | 显示全部楼层 |阅读模式
GNU ARM汇编快速入门" N8 m, B( i- c' Q9 q9 \# K  z
以前用ARM的IDE工具,使用的是ARM标准的汇编语言。现在要使用GNU的工具,当然要了解一点GNU ARM汇编的不同之处。其实非常的简单,浏览一下文档然后再看看程序就完全可以搞定了,或者你硬着头皮看GNU ARM的汇编程序,用不了多少时间你就就可以无师自通了。
; y# T0 e# v& p$ L- k
! X3 d8 j/ {6 U: j9 mARM汇编语言源程序语句 ,一般由指令、伪操作、宏指令和伪指令作成。ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令。 & c7 K7 c  y) h# _6 Q
, C. c( l$ l6 G- t/ O" a
目前常用的ARM编译环境有2种:
: l5 _' ~. |4 F9 O8 XARMASM: ARM公司的IDE中使用了CodeWarrior的编译器,绝大多数windows下的开发者都在使用这一环境,完全按照ARM的规定;
- ~5 x6 D6 x; mGNU ARM ASM:GNU工具的ARM版本,与ARMASM略有不同; , c7 v; G( V5 G8 `
$ a, ]) m# E2 n0 q  G
关于CodeWarriror ARM汇编的书和文章很多,本文假定你已经完全了解ARMASM,这里只说明GNU ARM汇编,并针对ARMASM给出说明。本文翻译自:GNU ARM Assembler Quick Reference, 本人水平有限,错误难免,转载随意,请注明出处。英文原文地址不详。
6 G9 Z2 u' {! Q! {0 v. m: p1 l* p& n! d0 {4 A% S1 n( s

$ O& l; m/ _4 f1 k7 I4 |- oGNU ARM 汇编快速入门) A; d+ [2 X; j# M5 ]
任何汇编行都是如下结构:
3 y6 z6 z) b. Y- P5 W[<label>:] [<instruction or directive>} @ comment
6 y4 }; f; l; u/ v) R" i[<标签>:] [<指令>} @ 注释3 _" x. w( ]( S0 t# n
GNU ARM 汇编中,任何以冒号结尾的都被认为是一个标签,而不一定非要在一行的开始。下面是一个简单的例子,这段汇编程序定义了一个"add"的函数,该函数返回两个参数的和:1 [2 x8 w+ z3 i% B
.section .text, “x”! g! t/ b% e- k1 x
.global add @ give the symbol add external linkage
2 r% K: J" i% S+ W/ `* y8 \add:( Y) W2 w7 Y: |1 M) s4 p
ADD r0, r0, r1 @ add input arguments
- P. R1 y) }3 i! N  X# Z3 [/ yMOV pc, lr @ return from subroutine
% l  U6 a. C& ?& C0 N  y% q@ end of program
7 Y# U1 I2 g0 x% B2 ]( w9 MGNU ARM汇编伪指令
3 C/ S( W- w1 L( t1 z
: q5 Z# |! I( X下面列出了一些GNU ARM汇编伪指令,并给出了相应说明。
. s, ~: k% w. N. H8 H
; G9 Q4 {: |; l# F$ P.ascii “<string>” 在汇编中定义字符串并为之分配存储空间(与armasm中的DCB功能类似)。
7 m$ b  y: O( b5 {' m.asciz “<string>” 和.ascii类似, 但不分配存储空间。
0 M6 @1 R; v1 T! k- W$ `, Z.balign <power_of_2> {,<fill_value> {,<max_padding>} }
2 s& y4 D" w- P& ]$ Z以某种排列方式在内存中填充数值。 (该指令与armasm中的ALIGN类似)。9 V7 Z% i9 ?; V& K- g3 L7 @2 Z
power_of_2表示排列方式,其值可为4,8,16或32,单位是byte; & W  O* {0 t9 p1 S1 O
fill_value是要填充的值;
3 t! {  B' M, ]) \4 {0 }, Tmax_padding最大的填充界限,请求填充的bytes数超过该值,将被忽略。2 q5 l# u5 r& i2 M+ ]
.byte <byte1> {,<byte2>} … 定义一个或多个Byte,并为之分配空间(与armasm的DCB类似)。  
! j/ T- r3 @; x9 E; e.code <number_of_bits> 设定指令宽度,16表示Thumb,32表示ARM assembly
0 ^  M/ W3 I- k9 n: e' X- m(和armasm中的CODE16,CODE32相同)。. a% l) K5 x/ C/ v/ ~6 ~2 ^
.if  / l) f) k4 \- d
.else
9 T% C7 @9 q! J/ U% n) |8 {.endif & |8 v/ U1 B1 I0 r5 |3 i1 z" m& h! E
预编译宏(与armasm中的IF ELSE ENDIF相同)。4 D( J/ f6 |! x8 y: a7 O* r
.end 汇编文件结束标志,常常省略不用。, \- T3 D/ @2 ~( }" q; ?

; A! b4 G3 T' g( M" R0 `.endm 宏结束标志。
3 B& p2 [2 e# O3 t5 p.exitm 宏跳出。 + _) I* j& k7 {4 w
.macro <name> {<arg_1} {,<arg_2>} … {,<arg_N>}
6 Z1 c& p4 t  z: L, A4 Q, q6 R定义一段名为name的宏,arg_xxx为参数。
! y% z1 X$ X: `( ]/ x" ~7 Q" H7 @必须有对应的.endm结尾。9 X, k9 b! A5 \
可以使用.exitm从中间跳出宏。(与armasm中的MACRO, MEND, MEXIT相同)。
8 n0 d9 D* z0 G: t- c/ i4 K在使用宏参数时必须这样使用:“\<arg>”。
- d& m* i- I) F& f例如:
( p9 g8 m9 b2 \( n[CODE].macro SHIFTLEFT a, b
, C, {" g: m0 V$ t1 L. G, b8 Q( l& s.if \b < 0" g5 r7 V2 Y4 w. M0 V
MOV \a, \a, ASR #-\b$ L. {& q: @; D$ u
.exitm/ r. k. g5 H" R' Y7 N/ {) K
.endif
9 S+ e$ G0 k- F& Y, X5 ?" h  SMOV \a, \a, LSL #\b: ]: O2 j8 K! S. I) A% S; T8 F
.endm
+ G; i2 l9 C- t. f
0 E9 L$ D7 ~" k) t.rept <number_of_times> 循环执行.endr前的代码段number_of_times次。
/ U& [. r* Z- a  y  D8 z(与armasm中的WEN相似)* G3 u/ t- B  S1 V+ A

3 z, [/ M1 ]2 K8 j.irp <param> {,<val_1>} {,<val_2>} …
+ {' A& V: l; `# l, h$ p+ K循环执行.endr前的代码段,param依次取后面给出的值。
- f. e5 x# E/ K  i4 @  U  F在循环执行的代码段中必须以“\<param> ”表示参数。
5 M7 M, n7 k( C  w7 S; A8 A1 h, J' _
.endr 结束循环(与armasm中的WEND相似)./ L: h. B8 Q' J
.equ <symbol name>, <value> 为一个标号赋值,类似C中的#define。(与armasm中的EQU相同)
# U. \( I: T% T( H" |' _$ |.err 编译错误报告,将引起编译的终止。- s6 S( H( y8 }. ?4 k# I" T
.global <symbol> 全局声明标志,这样声明的标号将可以被外部使用。(与armasm中的EXPORT相同)。
" u: j4 U& X( s.hword <short1> {,<short2>} …
& P7 n$ W7 V: T$ k插入一个16-bit的数据队列。(与armasm中的DCW相同); J& N2 D: j* Y  c
.ifdef <symbol> 如果 <symbol>被定义,该快代码将被编译。以 .endif结束。; y: Y9 {( c9 |: Q( C9 a
.ifndef <symbol> 如果 <symbol>未被定义,该快代码将被编译。以 .endif结束。5 l9 R7 e( R- }& q
.include “<filename>” 包含文件。(与armasm中的INCLUDE 或者C中的#i nclude一样). ~; W9 o( d) n0 H; O: f5 `
<register_name> .req <register_name>
& ^% w' [/ m, [7 U% C+ [# m定义一个寄存器,.req的左边是定义的寄存器名,右边是使用的真正使用的寄存器。# y* c2 Z% {' |  V8 j- d6 S# Q
(与armasm中的RN类似)
$ m8 ^8 D  Z* O. I# K例如:acc .req r0
( c: M7 D4 x( M1 I[CODE].section <section_name> {,”<flags>”}( J8 n9 V% M; b# a! }1 N# w. {
开始一个新的代码或数据段。.text, 代码段;.data, 初始化数据段;.bss, 未初始化数据段。 6 \* N/ ?  d0 D8 I7 _$ p
这些段都有缺省的标志(flags),联接器可以识别这些标志。(与armasm中的AREA相同)。) F! B; l$ }8 h+ @: L
下面是ELF格式允许的段标志
' V2 V. n. F; o  }<标志> 含义
1 W& T9 Q% `% ]% ~! r  O! ga 允许段0 K# L/ K( q+ r1 L6 m# ]
w 可写段; I) {; F7 G. j7 F; c1 e* M0 z
x 执行段, f4 X, W( g- W/ t
.set <variable_name>, <variable_value> 变量赋值。(与armasm中的SETA相同)
1 q- K* D4 v# ~+ y, r" d1 H- w.space <number_of_bytes> {,<fill_byte>}& f6 A3 p+ r- Z
分配number_of_bytes字节的数据空间,并填充其值为fill_byte,若未指定该值,缺省填充0。$ o: I9 E; ^( ~9 `
(与armasm中的SPACE功能相同)
9 r% ~! C* D6 S! Q; E  H/ n.word <word1> {,<word2>} …
! V- W5 }* @- l- q1 y, l插入一个32-bit的数据队列。(与armasm中的DCD功能相同)
. `& y5 z0 V& o0 h9 F  G. W' [" x" l% T$ Q0 k2 L
GNU ARM汇编特殊字符和语法  p- s' M. U2 ?
  R+ Q/ h" C' r8 H) U6 u
代码行中的注释符号: ‘@’
/ b' ?3 [) M3 M; S5 K7 G5 i* q: E整行注释符号: ‘#’
) S. _7 L3 K8 L7 v* n语句分离符号: ‘;’
/ P/ e2 O$ G3 i! {1 ^7 U直接操作数前缀: ‘#’ 或 ‘$’
5 n2 Q. m5 q. D4 m& v.arm 以arm格式编译,同code32 ! z* A: ]- E" j0 I! Z: N# V5 g9 q6 t
.thumb 以thumb格式编译,同code16
' Y) o5 s: }; Z" r6 y4 t- v.code16 以thumb格式编译
& W3 t' {6 ]! I) y4 _.code32 以arm格式编译5 Z9 w" B7 [3 H
篇后语:# {; @5 k& T5 U: k! G7 f$ @
4 f7 \7 j* \$ ?, }& a- D
更详细的使用说明请参照:ARM Architecture Reference Manual, Addison-Wesley ISBN 0-201-73719-1! I& `0 z+ W/ U- ]
补充:( Y1 {) f8 E# I7 ~
# x- @, O, U4 n1 |* B2 n* `0 N, Y
4 ARM GNU常用汇编语言介绍
3 B& m/ ?8 N0 x! p8 E! }4 Z8 e4 Y4.1 ARM GNU常用汇编伪指令介绍
' Y$ `: y& \3 h7 |( d6 w1. abort  f' |0 e0 Q% R/ F0 X: `5 u6 c9 N
.abort: 停止汇编
1 n8 `; o9 y& ?% G; g! A.align abs-expr1, abs-expr2: 以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第2 B$ ~( g! x3 q3 t, R1 L& D* |
二个表达式值表示填充的值.7 ]5 S4 U8 R5 h" X
2. if...else...endif
/ K4 K4 X( ]! y) s" X.if
( K8 p/ i1 F9 B) `.else
% a6 e3 G3 q# M" ~- v) l.endif: 支持条件预编译
: j) r* n$ {6 M& }" j3. include
2 p' p" h  n, m5 m9 ^, M9 y.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中.
) U/ N, t3 V* G5 g$ `4. comm
# `. ]( F. q+ r.comm symbol, length:在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length.      Ld连接器在连接会- o; Z1 B2 ~  f2 y8 ^7 @, a
为它留出空间.
7 h9 W& d' i+ J/ v5. data0 S* w6 j3 m) ~! b3 `, S
.data subsection: 说明接下来的定义归属于subsection数据段.+ S1 B' @* X6 E: `$ i6 k- g) G7 H
6.      equ
7 N7 R! S% o$ u- q" Y" q; a; |.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.; `. B9 a( i5 V: F
7. global+ L" R" A1 t" Z, W* l
.global symbol: 定义一个全局符号, 通常是为ld使用.2 e: ~( H+ T( j. s: p% F
8. ascii
0 U; [! f. e* f) H0 m3 q; s.ascii "string": 定义一个字符串并为之分配空间.
6 g$ M: o7 E/ @- F( m9. byte3 ~6 i( v, ]! w" k6 x7 G: Q" Q$ t% S
.byte expressions: 定义一个字节, 并为之分配空间.; U" u! w/ M$ D# A+ m
10. short
! ~2 {$ z% Q8 Y) D% d.short expressions: 定义一个短整型,      并为之分配空间.
$ z9 G8 L( `) C9 ?" F11. int" D9 x0 x( t2 r* s  b
.int expressions: 定义一个整型,并为之分配空间.& E5 h6 D3 G$ W& m
12 long
, ^' _% c& L4 v% d+ e: W: U.long expressions: 定义一个长整型, 并为之分配空间.  q* V% t3 e; _9 E% d
13 word
& B$ p5 S' [: V.word expressions: 定义一个字,并为之分配空间, 4bytes.
9 j8 y9 P9 v) a) g# g14. macro/endm
( o$ H* P( Z- J7 ]* V5 Z.macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束.
4 K! X( l$ Z* `) U3 j+ ?) v15. req
$ R/ C3 W/ y# X# zname .req register name:      为寄存器定义一个别名.
4 ]) H0 y  c+ u$ \5 w& }16. code' Z# V) J7 ]( [  P' g# ^! I
.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令.0 s- \" Y1 R8 i. ~# y  P3 P, W' {
17. ltorg; _& x! l1 H( y7 o9 V% j
.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间.2 U  D3 A& ?* c' l/ ?
4.2 ARM GNU专有符号
3 ~8 q3 v& p& z; [+ h0 Q- z5 \8 h* X1. @" `4 Z+ ]3 ?4 i* X. x
表示注释从当前位置到行尾的字符.
0 j8 K* i8 T) o2. #
$ r* k1 }4 g6 U  i' m注释掉一整行.: b* O# j4 r; _- r* x2 G! l# g
3. ;
7 W4 a) H" V) u; d. T/ h8 t2 C# ^新行分隔符.
, z1 N& H* F2 E6 v4.3 操作码
2 q: O( P# Z! c+ I1. NOP
7 \! R0 f" T: N- }( @) }       nop5 z4 Y/ r: ~& [& o9 p+ r! p5 V% n
       空操作, 相当于MOV r0, r0
9 E- l9 A8 ]- z4 y2. LDR3 F! n9 C4 N0 R0 }( h  K
          ldr <register> , = <expression>
- z3 j! g3 `0 r1 p+ P       相当于PC寄存器或其它寄存器的长转移.8 ]5 }/ `( c; X* E% l
3.ADR
/ c/ g& R( b1 _5 ]3 n          adr <register> <label>7 q+ [5 F# D3 k$ p7 T
       相于PC寄存器或其它寄存器的小范围转移.' ^5 a3 \5 x( T: t0 b
       ADRL9 L+ k3 d$ P: g8 X* g7 E
          adrl <register> <label>
( D' x2 D7 L- x       相于PC寄存器或其寄存器的中范围转移.( u/ R5 u2 ~- `$ @
# e$ A  C* l" J1 f! q0 X1 y
原文地址:http://blog.csdn.net/lbsljn/archive/2009/06/17/4277640.aspx4 L* v7 t) k# m9 S( c! Z9 y

) |! K. d! i. o
2 s3 b' A; m& L( L1 \! p
  J: N3 Q& U+ P, H! M1 L

本版积分规则

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

GMT+8, 2026-1-11 16:57 , Processed in 0.034338 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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