一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3493|回复: 0

GNU ARM汇编快速入门

[复制链接]
发表于 2016-12-18 16:23 | 显示全部楼层 |阅读模式
GNU ARM汇编快速入门
0 e6 v5 I/ y" C5 @$ X& w4 P以前用ARM的IDE工具,使用的是ARM标准的汇编语言。现在要使用GNU的工具,当然要了解一点GNU ARM汇编的不同之处。其实非常的简单,浏览一下文档然后再看看程序就完全可以搞定了,或者你硬着头皮看GNU ARM的汇编程序,用不了多少时间你就就可以无师自通了。  d. F. |4 \' s" S  g" a  E
: w3 Y& S/ j' p, E# C/ L1 _
ARM汇编语言源程序语句 ,一般由指令、伪操作、宏指令和伪指令作成。ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令。 & x' H; ?9 `) {8 ], b" u
/ s3 e; ?/ f8 T* Z7 k2 e
目前常用的ARM编译环境有2种:
8 O* O% a* h" ^8 n3 x, y" s' LARMASM: ARM公司的IDE中使用了CodeWarrior的编译器,绝大多数windows下的开发者都在使用这一环境,完全按照ARM的规定;
+ C5 O0 {7 ?# m" _7 G' [2 U& zGNU ARM ASM:GNU工具的ARM版本,与ARMASM略有不同; ; N! r* p' t' t  q

" k* W) l3 u% A6 H关于CodeWarriror ARM汇编的书和文章很多,本文假定你已经完全了解ARMASM,这里只说明GNU ARM汇编,并针对ARMASM给出说明。本文翻译自:GNU ARM Assembler Quick Reference, 本人水平有限,错误难免,转载随意,请注明出处。英文原文地址不详。 0 Y% h- ~9 z' j

( A  W& r; o& P% g' a: K" j! B# {( u( V" L' `1 f
GNU ARM 汇编快速入门* y. P6 l2 h+ y$ \# Y2 G
任何汇编行都是如下结构:' h$ N# n/ H& L. G
[<label>:] [<instruction or directive>} @ comment
) E+ q5 \4 A0 l[<标签>:] [<指令>} @ 注释" U2 `0 a! `  Z2 }8 ?$ w1 z
GNU ARM 汇编中,任何以冒号结尾的都被认为是一个标签,而不一定非要在一行的开始。下面是一个简单的例子,这段汇编程序定义了一个"add"的函数,该函数返回两个参数的和:# M, I, Y- n5 p2 q. ]
.section .text, “x”
  q6 S" H2 o; @% R: {! W% w.global add @ give the symbol add external linkage
% J7 X; z4 a) x* A% kadd:
% @7 {  Z  J& B1 p+ @: L- hADD r0, r0, r1 @ add input arguments- X% |' d4 C! \; t% O
MOV pc, lr @ return from subroutine
: h" F  X" \3 v2 M0 S. E@ end of program
3 u3 h4 ]! B7 j& a; I7 i) hGNU ARM汇编伪指令3 Z- r1 v1 H$ A3 h3 p9 A
. c* }2 a* |: H% J& e2 @6 b
下面列出了一些GNU ARM汇编伪指令,并给出了相应说明。1 _" L6 `* C6 o; i- b& B" n# O

/ Y# m  t* L5 N1 E1 Z0 K.ascii “<string>” 在汇编中定义字符串并为之分配存储空间(与armasm中的DCB功能类似)。 2 C* J' @# b+ ^9 E6 L" m* L1 }+ S
.asciz “<string>” 和.ascii类似, 但不分配存储空间。2 P% P+ M; y4 a# h+ B: }& r4 C/ V
.balign <power_of_2> {,<fill_value> {,<max_padding>} } + g* j; \2 }0 \+ w) \5 W; A# e
以某种排列方式在内存中填充数值。 (该指令与armasm中的ALIGN类似)。: L5 c  Y/ M' p1 {. _
power_of_2表示排列方式,其值可为4,8,16或32,单位是byte;
8 T- l* V$ o1 V1 {7 ifill_value是要填充的值;
% ?9 S2 {& {0 S7 [: M$ \max_padding最大的填充界限,请求填充的bytes数超过该值,将被忽略。$ ?4 _) }! `5 I8 t" `$ c2 s
.byte <byte1> {,<byte2>} … 定义一个或多个Byte,并为之分配空间(与armasm的DCB类似)。  7 q# v% l6 l  j% I  x9 e
.code <number_of_bits> 设定指令宽度,16表示Thumb,32表示ARM assembly
1 A  \4 q1 Q$ c& M+ V  t; g5 w(和armasm中的CODE16,CODE32相同)。. e. c$ F% k  F9 n! R
.if  
" ~5 s9 k4 g  O. ]0 [4 B.else
  I2 d$ q$ i- N.endif
: f8 N# V+ n. N预编译宏(与armasm中的IF ELSE ENDIF相同)。- k: l1 O! T% O7 I% M
.end 汇编文件结束标志,常常省略不用。* k2 M2 X, B4 F: I! U* c" g; r
; w% S& q$ M* H) U' `
.endm 宏结束标志。 & Z' U7 L9 j8 }3 `
.exitm 宏跳出。   t' \3 R5 d. r- N1 D. p  ?; r
.macro <name> {<arg_1} {,<arg_2>} … {,<arg_N>}   g$ O- i" j7 o, a, U& ^# y1 {! x
定义一段名为name的宏,arg_xxx为参数。% |* D! {- h* T1 W& _
必须有对应的.endm结尾。
1 ?  }, H8 d: c9 S" ~8 B2 j可以使用.exitm从中间跳出宏。(与armasm中的MACRO, MEND, MEXIT相同)。
- D( g! u- ]. Y在使用宏参数时必须这样使用:“\<arg>”。
# l9 o" h. O0 N7 V( {0 f$ C& F$ w例如:
% Y8 t! ~: d- ~[CODE].macro SHIFTLEFT a, b
1 `9 i/ N( g6 u% a; D/ ~" T.if \b < 0
* z* `) {7 x4 p" UMOV \a, \a, ASR #-\b
1 |/ u5 W0 }6 I9 t.exitm
5 Q' Q# T: S5 e+ V6 ~# Z5 t.endif
* Y; N1 U+ j* s' y$ A- }MOV \a, \a, LSL #\b0 B! t( P; `& l5 y+ z  T0 \* ]) D4 h
.endm0 n# F5 ]- I6 j: M4 P5 Z7 u4 y

: ^! l* }1 I3 a+ x.rept <number_of_times> 循环执行.endr前的代码段number_of_times次。
% v% K# M2 U' h' V' [(与armasm中的WEN相似)
# D# H/ B1 `! u/ y* p9 e
/ q/ n* g5 t. q+ p.irp <param> {,<val_1>} {,<val_2>} …
3 Q& Z, U) P2 e0 v! N循环执行.endr前的代码段,param依次取后面给出的值。; t& {$ q1 D/ G7 i5 t: y2 v
在循环执行的代码段中必须以“\<param> ”表示参数。3 }! z: u  h2 p- n9 j
8 N5 V( B5 L' I0 n
.endr 结束循环(与armasm中的WEND相似).# p4 ]# L4 q4 @8 d8 [1 p9 M% h
.equ <symbol name>, <value> 为一个标号赋值,类似C中的#define。(与armasm中的EQU相同)
8 k$ I7 p# P8 ?- ?.err 编译错误报告,将引起编译的终止。1 U+ y  L# u: X4 u
.global <symbol> 全局声明标志,这样声明的标号将可以被外部使用。(与armasm中的EXPORT相同)。& {& W1 i6 @- N5 y5 w2 \2 i
.hword <short1> {,<short2>} …/ Y- |" ]' Q  \: R
插入一个16-bit的数据队列。(与armasm中的DCW相同). ~( W2 O- A' q3 ~& ~! @
.ifdef <symbol> 如果 <symbol>被定义,该快代码将被编译。以 .endif结束。2 n8 G  D" J( m* G2 v, ]
.ifndef <symbol> 如果 <symbol>未被定义,该快代码将被编译。以 .endif结束。( Z; c) |: @7 [1 W8 l
.include “<filename>” 包含文件。(与armasm中的INCLUDE 或者C中的#i nclude一样)
  W" \7 u( E5 C  x( [6 C' B<register_name> .req <register_name>! b  c2 @+ `" t
定义一个寄存器,.req的左边是定义的寄存器名,右边是使用的真正使用的寄存器。8 [5 _1 C$ ~2 D. c$ ^
(与armasm中的RN类似)$ H& {4 D# M- C/ T6 K2 p/ p+ K
例如:acc .req r0/ j- ~; V! a6 n3 C
[CODE].section <section_name> {,”<flags>”}
  [! E! l1 d; D! w! x$ \3 f2 i% z开始一个新的代码或数据段。.text, 代码段;.data, 初始化数据段;.bss, 未初始化数据段。
. I$ Q7 D' I- J3 z+ L# T& _这些段都有缺省的标志(flags),联接器可以识别这些标志。(与armasm中的AREA相同)。3 J- I6 c/ _9 @  o8 a' ~) f0 ]
下面是ELF格式允许的段标志
5 ?* `) ?, p4 D7 o7 T# R<标志> 含义
$ [$ j1 ?* n. ?0 G" Va 允许段
0 D' |9 c8 E5 g$ o" |w 可写段
2 g5 W4 x: }$ @  u+ c1 Ex 执行段
# U( H- S; e# T" L4 J5 _, F.set <variable_name>, <variable_value> 变量赋值。(与armasm中的SETA相同)& ?6 M* l* }: M8 s/ I$ f5 }2 P
.space <number_of_bytes> {,<fill_byte>}: B$ Z" q# Z$ Z1 }) B9 G
分配number_of_bytes字节的数据空间,并填充其值为fill_byte,若未指定该值,缺省填充0。7 w8 J: X; z: A6 ]& Q4 I$ u
(与armasm中的SPACE功能相同)
; W& P0 A( F( a% ^& v.word <word1> {,<word2>} …
+ S, L) d( y/ A* g; [7 m插入一个32-bit的数据队列。(与armasm中的DCD功能相同); R( `- b$ K3 g9 l

) D& Y- _$ t) l. d. KGNU ARM汇编特殊字符和语法* X  w0 x; F( ?8 f* u  I0 m
  }, z9 R+ y' Y6 E! y: S
代码行中的注释符号: ‘@’
" R* c: }3 I6 S3 V$ U6 \整行注释符号: ‘#’
, s9 c4 s* o8 }$ {: w" T! e语句分离符号: ‘;’2 s! n5 ^: `8 `( S8 b. C  _
直接操作数前缀: ‘#’ 或 ‘$’
/ v% U0 |% H: S- R/ \4 H. p.arm 以arm格式编译,同code32
' i6 e6 z# \1 K% z2 t4 D, H, l.thumb 以thumb格式编译,同code16! a6 T5 B0 X  ?. a
.code16 以thumb格式编译: W4 i+ f) P$ I$ w) `' c1 N
.code32 以arm格式编译
7 A6 K: D: b5 W7 \$ `! a) ~, g篇后语:' ~* k+ N& i4 {, _- k- r
' h; ]/ p$ U6 X) o% j* V
更详细的使用说明请参照:ARM Architecture Reference Manual, Addison-Wesley ISBN 0-201-73719-16 G4 v+ o/ p" L; m9 _7 d/ T
补充:
' u+ i9 a& \. J" O% ^2 N# w2 D3 J
4 ARM GNU常用汇编语言介绍1 c5 w4 _! P1 D
4.1 ARM GNU常用汇编伪指令介绍
/ f9 n& Q8 {3 ], K5 [: d1. abort5 P# C! I, y! a/ K" l8 F( z! A
.abort: 停止汇编) H1 T" Z7 D2 \
.align abs-expr1, abs-expr2: 以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第
* ]  h- V, D, g二个表达式值表示填充的值.8 t3 O+ ]; q$ e7 l2 H
2. if...else...endif
" a5 s8 L0 B0 S.if3 A- L) m5 }% h# @+ j2 o
.else1 |9 m. E' M' }& A
.endif: 支持条件预编译
4 t) ?7 |- C6 K: `& K+ C2 d3. include
. W. z5 ?+ x) o' u) [1 F.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中." Z- P; S; _' N; J2 k; E- x2 }
4. comm) l7 O/ Q4 b$ }9 K( K0 _
.comm symbol, length:在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length.      Ld连接器在连接会: }# K( e$ f+ Q0 [' s
为它留出空间.
* q# {5 S/ U! c5 W) M/ u7 a' i1 C9 B5 j5. data
8 d4 ]" D/ T  s" j) P.data subsection: 说明接下来的定义归属于subsection数据段.; U7 f4 s( d7 W; f5 c
6.      equ
! W' O! {. |# w: ?.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.) H/ o+ p8 @& U4 o2 _9 g: `0 I+ N! e
7. global0 |+ `/ K3 f$ ?% D+ Q. b
.global symbol: 定义一个全局符号, 通常是为ld使用.( ^5 [, R9 c+ [
8. ascii7 a. f# i  C; a7 M2 }% E: E
.ascii "string": 定义一个字符串并为之分配空间.! M7 E/ v( M- u" Z
9. byte
# K: S9 o0 `7 _$ L.byte expressions: 定义一个字节, 并为之分配空间./ ^: Q" x3 F+ x, F
10. short. i# I" ]( p# h% T3 I
.short expressions: 定义一个短整型,      并为之分配空间.1 @9 }8 O. b. D7 y6 A
11. int
+ o% d3 p5 |% ]8 G.int expressions: 定义一个整型,并为之分配空间.
) q5 i8 m0 |. h6 B) T3 h: D+ G12 long
8 \$ J$ ^* V6 F% ].long expressions: 定义一个长整型, 并为之分配空间.. G7 z9 `1 B) B$ z- @  V
13 word3 B, ~# b; H2 m0 b: i; J( w
.word expressions: 定义一个字,并为之分配空间, 4bytes.$ E$ w. Z9 B, h) v. W5 ^! V
14. macro/endm% V# u# Y: E. y2 Z. q/ q
.macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束.
& G' A: @1 y4 n: ^0 n15. req- g) c- ?( B) a! J7 {
name .req register name:      为寄存器定义一个别名.
( x) u, S6 v7 w+ R1 x5 s% t1 C16. code
" d% P3 ]' K/ _) [( D. ^+ j; t.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令.
% K0 f8 Q. O3 b7 E( B! S17. ltorg. p: i5 j, t% y! H& f. z. r% @
.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间.$ l) h6 g$ b, p9 [2 G
4.2 ARM GNU专有符号5 {0 S# A; t4 @; B. I$ O
1. @
( i0 |% P% v# v7 P表示注释从当前位置到行尾的字符.
, q! ~; q1 c9 ^) I2. #% b, T9 s) o. B9 `. [
注释掉一整行.1 k+ x8 H8 B* A, C+ ^! V
3. ;2 H6 R- M+ \+ G" F1 f- K% u+ P7 m
新行分隔符.5 {4 c0 X6 `$ P% P: I& S
4.3 操作码
! }1 S/ R& B) n9 ?1. NOP
; U$ O% D, X. f( w0 [0 U5 e; i       nop7 D8 B5 ^- p8 q' @2 B' e6 h5 [- R
       空操作, 相当于MOV r0, r0" R4 R" `" ~( J' a, y" Z
2. LDR. U! J% F  q8 E8 F% k
          ldr <register> , = <expression>
! ?3 ]! ^/ j% o$ D       相当于PC寄存器或其它寄存器的长转移.3 y3 S! e5 [( ~
3.ADR
* q% D% ~! g. z$ {+ @$ f4 v1 ]          adr <register> <label>
/ c, c# f5 X6 w0 X8 b0 U4 p       相于PC寄存器或其它寄存器的小范围转移.
: @* P* v* j! @; f' x9 I7 J       ADRL( O& j1 R) d! G# v- c
          adrl <register> <label>6 [" I2 B: P; t8 Q1 Q* F$ \
       相于PC寄存器或其寄存器的中范围转移.
7 [% o7 a" d5 N5 r! G5 _+ C! a0 y) o( ^) `" @$ j! ~& D
原文地址:http://blog.csdn.net/lbsljn/archive/2009/06/17/4277640.aspx
: |$ L" |# a* U
* Q: j0 J6 B/ j7 {/ ^
1 A: R' S4 ^) D6 m: E
( z5 c, H6 _- B" o

本版积分规则

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

GMT+8, 2025-10-28 03:17 , Processed in 0.029866 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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