当前位置:文档之家› ARM指令汇编语言

ARM指令汇编语言

ARM指令汇编语言
ARM指令汇编语言

ARM指令集和汇编语言程序

姓名:何瑞平

学号:201120928

专业:电路与系统

本章主要介绍以下内容:

一、ARM寻址方式

包含9种:

立即数寻址

寄存器寻址

寄存器移位寻址

寄存器间接寻址

基址变址寻址

相对寻址

多寄存器寻址

块拷贝寻址

堆栈寻址

寻址空间:51系列是16位地址总线,寻址空间为:215 。ARM系列为32位地址总线,寻址空间为:231

1.1立即数寻址

在立即数寻址中,操作数本身直接在指令中给出,取出指令也就获得了操作数,这个操作数也称为立即数。

例:

ADD R0,R1,#5;R0=R1+5

MOV R0,#0x55;R0=0x55

其中:操作数5,0x55就是立即数,立即数在指令中要以“#”为前缀,后面跟实际数值。十进制立即数表达举例:#0005、#01234;

十六进制立即数表达举例:#0x0005、#0x0FFFF;

1.2寄存器寻址

在寄存器寻址方式下,寄存器的值即为操作数,寄存器本身就是操作数地址。在51系列单片机中,可寻址的寄存器是当前工作寄存器R0~R7,A、B和DPTR。

在ARM系列的任一个模式,都有R0~R14、PC、CPSR。

例:

ADD R0,R1,R2 ;R0=R1+R2

MOV R0,R1 ; R0=R1

1.3寄存器移位寻址

寄存器移位寻址是ARM 特有的寻址方式,其操作数由寄存器的数值做相应移位而得到。 移位的方式在指令中以助记符的形式给出,而移位的位数可用立即数或寄存器寻址方式表示。 例:

ADD R0,R1,R2,ROR #5

;R0=R1+R2循环右移5位 MOV R0,R1,LSL R3

;R0=R1逻辑左移R3位

移位操作在ARM 指令集中不作为单独的指令使用,ARM 指令集共有5种位移操作。

1.4 ARM 指令集的5种位移操作

1.4.1 LSL (Logical Shift Lef )逻辑左移 :

向左移位,左侧移出的位丢失;右端空出位补0;

注:最后一个左移出的位存放于状态寄存器CPSR 的C 位中。移出n 位相当于乘以2的n 次幂。

指令格式:Rx ,LSL 举例:

R4,LSL#06 表明把R4的值逻辑左移6位,空位补0,把最后移出的位赋给程序状态寄存器CPSR 的C 位。

1.4.2 LSR (Logical Shift Right )逻辑右移 :

向右移位,右侧移出的位丢失;左端空出位补0;

注:最后一个右移出的位存放于状态寄存器CPSR 的C 位中。移出n 位相当于除以2的n 次幂。

指令格式:Rx ,LSR 举例:

R5,LSR#02 表明把R5中的数据右移2位,空位补0,把最后移出的位赋给程序状态寄存器的c 位。

1.4.3 ASR (Arithmetic Shift Right )算术右移 : 向右移位,移出的位丢失,最左端保持不变。

310031

注:最后一个右移出的位存放于状态寄存器CPSR 的C 位中。这种移位对有符号数据使用时可保持符号位不变。 指令格式:Rx ,ASR 举例:

R4,ASR#04 表明R4内数据向右移4位,符号位不变,最后移出的位也送入状态位C 中。

1.4.4 ROR (Rotate Right )循环右移 :

向右移位,右端移出的位填充在左端空位处。

注:最后一个右移出的位同时存放于状态寄存器CPSR 的C 位中。 指令格式:Rx ,ROR 举例:

R4,ROR#03 表明把R4内的数据向右移3位,移出的位填充到左端空位处,把最后一个右移出的位同时存放于状态寄存器的C 位中。

1.4.5 RRX (Rotate Right extended By 1 Place ) 带扩展的循环右移:

向右只移一位,左侧空位由状态寄存器C 位填充,右侧移出的位移进位状态位C 中

这种移位多用于多位数计算中。 指令格式:Rx ,RRX 举例:

R2,RRX 表明R2内的数据向右移一位,把右侧移出的位送入状态寄存器C 中,C 位中的值放入左侧的空位处。

注意:在各种移位方式中,假设移位位数为n ,则n 须遵守以下规则: ASR 1≤n ≤32 LSL 0≤n ≤31 LSR 1≤n ≤32 ROR 1≤n ≤31

RRX 只右循环一位

310

310310C

1.5 寄存器间接寻址

寄存器中的值为操作数的物理地址,而实际的操作数存放在存储器中。在51系列,可间接寻址的寄存器有R0、R1,DPTR。在ARM中,可间接寻址的寄存器有R0~R15.

例:

STR R0,[R1] ;[R1]=R0

LDR R0,[R1] ;R0=[R1]

1.6 基址变址寻址

将寄存器(称为基址寄存器)的值与指令中给出的偏移地址量相加,所得结果作为操作数的物理地址。

例:

LDR R0,[R1,#5] ; R0=[R1+5]

基址R1,偏移量是立即数5。

LDR R0,[R1,R2] ; R0=[R1+R2]

1.7 相对寻址

相对寻址同基址变址寻址相似,区别只是将程序计数器PC作为基址寄存器,指令中的标记作为地址偏移量。

例:

BEQ process1

……

process1

……

1.8 多寄存器寻址

在多寄存器寻址方式中,一条指令可实现一组寄存器值的传送。连续的寄存器间用“-”连接,否则用“,”分隔。

例:

LDMIA R0,{R1-R5}

;R1=[R0],R2=[R0+4],R3=[R0+8]

;R4=[R0+12],R5=[R0+16]

指令中IA表示在执行完一次Load操作后,R0自增4。该指令将以R0为起始地址的5个字数据分别装入R1,R2,R3,R4,R5中。

1.9 块拷贝寻址

块拷贝寻址可实现连续地址数据从存储器的某一位置拷贝到另一位置。

例:

LDMIA R0,{R1-R5};

STMIA R1,{R1-R5};

第一条指令从以R0的值为起始地址的存储单元中取出5个字的数据,第二条指令将取出的数据存入以R1的值为起始地址的存储单元中。实际上是多寄存器寻址的组合。

1.10 块拷贝寻址

块拷贝寻址可实现连续地址数据从存储器的某一位置拷贝到另一位置。

例:

LDMIA R0,{R1-R5};

STMIA R1,{R1-R5};

第一条指令从以R0的值为起始地址的存储单元中取出5个字的数据,第二条指令将取出的数据存入以R1的值为起始地址的存储单元中。实际上是多寄存器寻址的组合。

1.11 堆栈寻址

堆栈是一块用于保存数据的连续内存,是按先进后出(FILO)的原则存取数据的存储区。使用一个称作堆栈指针的专用寄存器指示当前的操作位置,堆栈指针总是指向栈顶。

当堆栈指针指向最后压入堆栈的数据时,称为满堆栈(Full Stack),而当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(Empty Stack)。同时,根据堆栈的生成方式,又可以分为递增堆栈和递减堆栈。

当堆栈由低地址向高地址生成时,称为递增堆栈;当堆栈由高地址向低地址生成时,称为递减堆栈。这样就有4种类型的堆栈工作方式。

ARM堆栈的几种形式

1.满栈递增方式FA(Full Ascending)

与51系列的堆栈方式相同,堆栈指针指向最后入栈的数据位置。数据入栈时,堆栈指针是增计数。

2.空栈递增方式EA(Empty Ascending)

和满栈递增的区别在于,堆栈指针指向下一个入栈数据的位置。

3.满栈递减方式FD(Full Descending)

堆栈指针指向最后入栈的数据,数据入栈时堆栈指针是减计数。

4.空递减方式ED(Empty Descending)

和满栈的区别在于,堆栈指针指向下一个入栈数据的位置。

堆栈寻址用于数据栈与寄存器组之间批量数据传输。

当数据写入和读出内存的顺序不同时,使用堆栈寻址可以很好的解决这问题。

例:

STMFD R13!,{R0,R1,R2,R3,R4};

LDMFD R13!,{R0,R1,R2,R3,R4}

第一条指令,将R0-R4中的数据压入堆栈,R13为堆栈指针;

第二条指令,将数据出栈,恢复R0-R4原先的值。

二、ARM指令集的基本特点

ARM指令系统简介

ARM9 处理器支持两种指令集,即32 位的ARM 指令集和16 位Thumb 指令集。ARM微处理器的指令集是加载/存储型的,即指令集仅能处理寄存器中的数据,而且处理结果都要放回寄存器中;而对系统存储器的访问则需要专门的加载/存储指令来完成。ARM指令集是特殊的指令集,32位编码包含的信息量很大,每一条语句完成的功能很强,在多寄存器操作指令中一次最多可以完成16个寄存器的数据传送。

ARM指令集按指令功能通常分为6大类:

◆跳转指令

◆数据处理指令

◆程序状态寄存器(PSR)处理指令

◆加载/存储指令

◆协处理指令

◆异常产生指令

ARM指令集格式如下图所示:

图2.1 ARM指令集格式

可以看到,[31:28]:条件代码域。[27:20]:指令代码域。[19:16]:地址基址Rn域。[15:12]:

目标或源寄存器Rd域。[11:0]:地址偏移或操作寄存器、操作数区域。

ARM指令集的基本特点

AMR指令集有很多的未定义指令。

ARM指令代码最高4位[31:28]是条件码域。ARM指令一般把[27:20]作为指令代码域。位[19:0]包含立即数、寄存器和偏移量等信息。

ARM指令集为寄存器寻址安排4位代码,可寻址16个寄存器。

多数情况下,目标寄存器Rd的寄存器编号存放在[15:12]位域。

位[20]是重要的条件标志(S)存放位。

2.1与Thumb指令集的区别

ARM指令集和Thumb指令集具有以下共同点:

⒈较多的寄存器,可以用于多种用途。

⒉对存储器的访问只能通过Load/Store指令。

2.2ARM 指令集和Thumb 指令集的不同点:

2.3与x86处理器的区别

x86指令集

非规整指令格式 即:非正交指令格式 二地址指令

指令隐含决定运算完毕后是否改变状态标志 状态标志位有6位 单一指令密度 有整数除法指令

专用条件判断指令进行程序分支 没有适合DSP 处理的乘加指令 运算指令能够访问存储器

ARM 指令集

规整指令格式

即:正交指令格式

三地址指令

由指令的附加位决定运算完毕后是否改变状态标志 状态标志位只有4位 有两种指令密度 无整数除法指令

大多数ARM 指令都可以条件执行 有适合DSP 处理的乘加指令 Load/Store 访存体系结构

2.4ARM指令格式

一条典型的ARM指令语法如下所示:

{}{S} , {,}

其中:

是指令助记符,决定了指令的操作。

例如:ADD表示算术加操作指令。

{} 是指令执行的条件(可选后缀),可选项。

{S} 决定指令的操作是否影响CPSR的值,可选项。

表示目标寄存器,必有项。

表示包含第1个操作数的寄存器,当仅需要一个源操作数时可省略

表示第2个操作数,可选项。

例如:

ADDEQS R0,R1,#8;

其中操作码为ADD,条件域cond为EQ,

S表示该指令的执行影响CPSR寄存器的值,目的寄存器Rd为R0,第一个操作数寄存器Rn为R1,第二个操作数OP2为立即数#8。

第2操作数

一、立即数控位的寄存器移位表达式

立即数控位,就是寄存器Rm移位的位数由立即数控制。在RRX移位方式不需要立即数控位。

Rm,LSL#03

本例中,移位位数为3.

移位方式有五种:

LSL n (0≤n≤31)

LSR n (1≤n≤32)

ASR n (1≤n≤32)

ROR n (1≤n≤31)

RRX 含进位标志C在内的循环右移

二、寄存器控位的寄存器移位表达式

所谓寄存器控位,就是寄存器Rm移位的位数由另一个寄存器Rs来控制,其中Rs为通用寄存器,不可使用R15。规定0≤Rs≤31.

Rm,LSR Rs

移位方式有五种,在RRX移位方式不需要寄存器控位。

第2操作数规范

第2操作数是一个无符号的32位数值,其规范是:一个8位的无符号数值常量,用0填充到32位后,循环右移偶次后得到的32位数值。

指令可选后缀

S后缀

使用S后缀时,指令执行后的程序状态寄存器CPSR的条件标志位将刷新,不使用则不刷新。举例:ADD R3,R5,R8

没有使用S后缀,条件标志位不刷新。

ADDS R3,R5,R8

使用S后缀,条件标志位将刷新。

S后缀适用范围:有些指令不需要加S后缀,在执行同同样可以刷新条件标志位,例如CMP、CMN和测试指令TEST。

S后缀使用目的:对条件位进行测试,看是否有溢出,是否有进位。在指令执行过程中判断是否大于,是否等于等。

注意:书写时,S后缀紧跟在指令助记符后面。

!后缀

当含有!后缀时,基址寄存器中的地址将发生变化,变化结果如下:

基址寄存器中的地址值(指令执行后)=指令执行前的值+地址偏移量

例 3.3分别执行下面两条指令有何区别?

LDR R3,[R0,#4]

LDR R3,[R0,#4]!

分析:在上述指令中,第1条指令没有后缀!,指令的结果是把R0加4作为地址指针,把这个指针所指向的地址单元所存储的数据读入R3,R0的值不变。第2条指令除了实现以上操作外,还把R0+4的结果送到R0中。两条指令加载到R3中的值一样,但前者基址寄存器R0的值不变,后者基址寄存器R0的值自动改变为方括弧内表达式的值。

使用!后缀需要注意如下事项:

(1)!后缀必须紧跟在地址表达式后面,而地址表达式要有明确的地址偏移量。

(2)!后缀不能用于R15(PC)的后面

(3)当用在单个地址寄存器后面时,必须确信这个寄存器有隐性的偏移量,例如“STMDB R1!{R3,R5,R7}”此时地址基址寄存器R1的隐性偏移量是4。

B后缀

说明指令所涉及的数据是一字节,不是一字或半字。

例如:

LDR R4,[R0,#20] R4=[R0+0x20],传送一字

LDRB R4,[R0,#20] R4=[R0+0x20],传送一字节

第一条指令传送的是32位的字,地址指向该字最低地址,需要地址对齐。第二条传送的是8位的字节,地址指向这个字节,没有地址对准要求。

注意:B指令紧跟在指令助记符后面

T后缀

指令在特权模式下对存储器的访问,将被存储器看作是用户模式的访问。

注意:

1.一般只用在字传送和无符号字节传送。

2.不能与前索引一起使用。

举例:LDRT R4,[R5];R4=R5 T模式

指令的条件执行

当处理器工作在ARM状态时,几乎所有的指令均根据CPSR中条件码的状态和指令的条件域有条件的执行。

当指令的执行条件满足时,指令被执行,否则指令被忽略。

每一条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面,和指令同时使用。

如:跳转指令B可以加上后缀EQ变为BEQ,表示“相等则跳转”,即当CPSR中的Z 标志置位时发生跳转。

指令条件码表:

例 3.4 下面三条指令有何区别?

ADD R4,R3,#1

ADDEQ R4,R3,#1

ADDS R4,R3,#1

分析:

第1条指令不带条件标志(无条件AL),指令的执行不受条件标志位的影响,完成加法运算:将R3的值加1存入寄存器R4。第2条ADD指令加上后缀EQ变为ADDEQ表

示“相等则相加”,即当CPSR中的Z标志置位时该指令执行,否则不执行。第3条指令的执行也不受条件标志的影响,但是由于附带了后缀S,这条指令执行的结果将影响CPSR中条件标志位的值。

条件后缀只是影响指令是否执行,不影响指令的内容,如上述ADDEQ指令,可选后缀EQ 并不影响本指令的内容,它执行时仍然是一条加法指令。

条件后缀和S后缀的关系如下:

(1)如果既有条件后缀又有S后缀,则书写时S排在后面

如:ADDEQS R1,R0,R2

该指令在Z=1时执行,将R0+R2的值放入R1,同时刷新条件标志位。

(2)条件后缀是要测试条件标志位,而S后缀是要刷新条件标志位。

(3)条件后缀要测试的是执行前的标志位,而S后缀是依据指令的结果改变条件标志。三、ARM指令集分类详解

一共有6种类型(53种主要助记符):

数据处理指令(22种主要助记符)

跳转指令(4种主要助记符)

Load/Store指令(16种主要助记符)

程序状态寄存器指令(2种主要助记符)

协处理器指令(5种主要助记符)

软件中断指令(2种主要助记符)

3.1 数据处理指令

3.2.1 MOV 数据传送指令

格式:MOV{}{S} ,;

功能:Rd=op1

op1可以是寄存器、被移位的寄存器或立即数。

例如:

MOV R0,#5 ;R0=5

MOV R0,R1 ;R0=R1

MOV R0,R1,LSL#5 ;R0=R1左移5位

3.1.2 MVN 数据取反传送指令

格式:MVN{}{S} ,;

功能:将op1表示的值传送到目的寄存器Rd中,但该值在传送前被按位取反,即Rd=!op1;

op1可以是寄存器、被移位的寄存器或立即数。

例如:

MVN R0,#0 ;R0=-1

3.1.3 ADD 加法指令

格式:ADD{}{S} ,,;

功能:Rd=Rn+op2

op2可以是寄存器,被移位的寄存器或立即数。

例如:

ADD R0,R1,#5 ;R0=R1+5

ADD R0,R1,R2 ;R0=R1+R2

ADD R0,R1,R2,LSL#5 ;R0=R1+R2左移5位

3.1.4 ADC 带进位加法指令

格式:ADC{}{S} ,,;

功能:Rd=Rn+op2+carry

op2可以是寄存器、被移位的寄存器或立即数;carry为进位标志值。该指令用于实现超过32位的数的加法。

例如:

第一个64位操作数存放在寄存器R2,R3中;

第二个64位操作数存放在寄存器R4,R5中;

64位结果存放在R0,R1中。

64位的加法可由以下语句实现:

ADDS R0,R2,R4 ;低32位相加,S表示结果影响条件标志位的值

ADC R1,R3,R5 ;高32位相加

3.1.5 SUB 减法指令

格式:SUB{}{S} ,,;

功能:Rd=Rn-op2

op2可以是寄存器、被移位的寄存器或立即数。

例如:

SUB R0,R1,#5 ;R0=R1-5

SUB R0,R1,R2 ;R0=R1-R2

SUB R0,R1,R2,LSL#5 ;R0=R1-R2左

3.1.6 RSB 反向减法指令

格式:RSB{}{S} ,,;

功能:同SUB指令,但倒换了两操作数的前后位置,即Rd=op2-Rn。

例如:

RSB R0,R1,#5 ;R0=5-R1

RSB R0,R1,R2 ;R0=R2-R1

RSB R0,R1,R2,LSL#5 ;R0=R2左移5位-R1

3.1.7 7.SBC 带借位减法指令

格式:SBC{}{S} ,,;

功能:Rd=Rn-op2-!carry

op2可以是寄存器、被移位的寄存器或立即数。

SUB和SBC生成进位标志的方式不同于常规,如果需要借位则清除进位标志,所以指令要对进位标志进行一个非操作。

例如:

第一个64位操作数存放在寄存器R2,R3中;

第二个64位操作数存放在寄存器R4,R5中;

64位结果存放在R0,R1中。

64位的减法(第一个操作数减去第二个操作数)可由以下语句实现:

SUBS R0,R2,R4; 低32位相减,S表示结果影响条件标志位的值

SBC R1,R3,R5; 高32位相减

3.1.8 RSC 带借位的反向减法指令

格式:RSC{}{S} ,,;

功能:同SBC指令,但倒换了两操作数的前后位置,即Rd=op2-Rn-!carry。

例如:

前提条件与SBC例子相同,操作数1-操作数2的实现语句需改为:

SUBS R0,R2,R4; 低32位相减,S表示结果影响寄存器CPSR的值

RSC R1,R5,R3; 高32位相减

3.1.9 MUL 32位乘法指令

格式:MUL{}{S} ,,;

功能:Rd=Rn×op2

该指令根据S标志,决定操作是否影响CPSR的值;其中op2必须为寄存器。Rn和op2的值为32位的有符号数或无符号数。

例如:

MULS R0,R1,R2 ;R0=R1×R2,结果影响寄存器CPSR的值

3.1.0 MLA 32位乘加指令

格式:MLA{}{S} ,,,;

功能:Rd=Rn×op2+op3

op2和op3必须为寄存器。Rn、op2和op3的值为32位的有符号数或无符号数。

例如:

MLA R0,R1,R2,R3 ;R0=R1×R2+R3

3.1.11 SMULL 64位有符号数乘法指令

格式:

SMULL{}{S} ,,,;

功能:Rdh Rdl=Rn×op2

Rdh、Rdl和op2均为寄存器。Rn和op2的值为32位的有符号数。

例如:

SMULL R0,R1,R2,R3;

R0=R2×R3的低32位;

R1=R2×R3的高32位;

3.1.12 SMLAL 64位有符号数乘加指令

格式:

SMLAL{}{S} ,,,;

功能:Rdh Rdl=Rn×op2+Rdh Rdl

Rdh、Rdl和op2均为寄存器。Rn和op2的值为32位的有符号数,Rdh Rdl的值为64位的加数。

例如:

SMLAL R0,R1,R2,R3;

R0=R2×R3的低32位+R0;

R1=R2×R3的高32位+R1;

3.1.13 UMULL 64位无符号数乘法指令

格式:

UMULL{}{S} ,,,;

功能:同SMULL指令,但指令中Rn和op2的值为32位的无符号数。

例如:

UMULL R0,R1,R2,R3;

R0=R2×R3的低32位;

R1=R2×R3的高32位

其中R2,R3的值为无符号数

3.1.14 UMLAL 64位无符号数乘加指令

格式:

UMLAL {}{S} ,,,;

功能:同SMLAL指令,但指令中Rn,op2的值为32位的无符号数,Rdh Rdl的值为64位无符号数。

例如:

UMLAL R0,R1,R2,R3;

R0=R2×R3的低32位+R0;

R1=R2×R3的高32位+R1

其中R2,R3的值为32位无符号数

R1,R0的值为64位无符号数

3.1.15 AND 逻辑与指令

格式:AND{}{S} ,,;

功能:Rd=Rn AND op2

op2可以是寄存器,被移位的寄存器或立即数。一般用于清除Rn的特定几位。

例如:

AND R0,R0,#5;

保持R0的第0位和第2位,其余位清0

3.1.16 ORR 逻辑或指令

格式:ORR{}{S} ,,;

功能:Rd=Rn OR op2

op2可以是寄存器、被移位的寄存器或立即数。一般用于设置Rn的特定几位。

例如:

ORR R0,R0,#5;

R0的第0位和第2位设置为1,其余位不变

3.1.17 EOR 逻辑异或指令

格式:EOR{}{S} ,,;

功能:Rd=Rn EOR op2

op2可以是寄存器、被移位的寄存器或立即数。一般用于将Rn的特定几位取反。

例如:

EOR R0,R0,#5;

R0的第0位和第2位取反,其余位不变

3.1.18 BIC 位清除指令

格式:BIC{}{S} ,,;

功能:Rd=Rn AND (!op2)

用于清除寄存器Rn中的某些位,并把结果存放到目的寄存器Rd中.

操作数op2是一个32位掩码(mask),如果在掩码中设置了某一位,则清除Rn中的这一位;未设置的掩码位指示Rn中此位保持不变。其中,op2可以是寄存器、被移位的寄存器或立即数。

例如:

BIC R0,R0,#5;

R0中第0位和第2位清0,其余位不变

3.1.19 CMP 比较指令

格式:CMP{} ,;

功能:Rn-op1

该指令进行一次减法运算,但不存储结果,根据结果更新CPSR中条件标志位的值。

该指令不需要显式地指定S后缀来更改状态标志。其中,操作数op1为寄存器或立即数。例如:

CMP R0,#5 ;计算R0-5,根据结果设置条件标志位

ADDGT R0,R0,#5;

如果R0>5,则执行ADDGT指令

3.1.20 CMN 反值比较指令

格式:CMN{} ,;

功能:同CMP指令,但寄存器Rn的值是和op1取负的值进行比较。

例如:

CMN R0,#5 ;把R0与-5进行比较。

3.1.21 TST 位测试指令

格式:TST{} ,;

功能:Rn AND op1

根据结果更新CPSR中条件标志位的值,但不存储结果。

用于检查寄存器Rn是否设置了op1中相应的位。

例如:

TST R0,#5 ;测试R0中第0位和第2位是否为1 。

3.1.22 TEQ 相等测试指令

格式:TEQ{} ,;

功能:Rn EOR op1

将寄存器Rn的值和操作数op1所表示的值按位作逻辑异或操作,根据结果更新CPSR中条件标志位的值,但不存储结果。

用于检查寄存器Rn的值是否和op1所表示的值相等。

例如:

TEQ R0,#5 ;判断R0的值是否和5相等。

3.2 程序分支

在51系列单片机能够引起程序分支的指令有两种:一种是条件(或无条件)分支;如:JZ、JNB等。另一种是子程序调用,如:ACALL、LCALL。而在ARM中,无条件分支指令,也无子程序调用指令,只有以下分支指令:

B分支指令:一个简单分支指令。

BL分支和链接指令:一种可以存储分支处地址的分支指令,可用于子程序调用。

BX分支和交换指令:一条可以在ARM指令集和Thumb指令集之间跳转的分支指令。

跳转指令用于实现程序的跳转和程序状态的切换。

ARM程序设计中,实现程序跳转有两种方式:

(1)跳转指令,

(2)直接向程序寄存器PC(R15)中写入目标地址值。

通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转。

使用跳转指令,其跳转空间受到限制。

3.2.1.B 跳转指令

格式:B{} ;

功能:PC= PC+ addr左移两位

addr的值是相对当前PC(即寄存器R15)的值的一个偏移量,而不是一个绝对地址,它是24位有符号数。实际地址的值由汇编器来计算.

addr的值有符号扩展为32位后,左移两位,然后与PC值相加,即得到跳转的目的地址。跳转的范围为-32MB~+32MB。

例如:

B exit; 程序跳转到标号exit处

exit …

3.2.2.BL 带返回的跳转指令 格式:BL{} ;

功能:同B 指令,但BL 指令执行跳转操作的同时,还将PC (寄存器R15)的值保存到LR 寄存器(寄存器R14)中。

该指令用于实现子程序调用,程序的返回可通过把LR 寄存器的值复制到PC 寄存器中来实现。

例如:

BL func; 调用子程序func …

func

MOV R15,R14; 子程序返回

3.2.3.BLX 带返回和状态切换的跳转指令 格式:BLX ;或BLX ;

功能:处理器跳转到目标地址处,并将PC (寄存器R15)的值保存到LR 寄存器(R14)中。

如果目标地址处为Thumb 指令,则程序状态从ARM 状态切换为Thumb 状态。

该指令用于子程序调用和程序状态的切换。 例如:

BLX T16; 跳转到标号T16处执行,T16后面的指令为Thumb 指令 …

CODE16 T16 后面指令为Thumb 指令 …

3.2.4.BX 带状态切换的跳转指令 格式:BX ;

功能:处理器跳转到目标地址处,从那里继续执行;

目标地址为寄存器Rn 的值和0xFFFFFFFE 作与操作的结果。 目标地址处的指令可以是ARM 指令,也可以是Thumb 指令。 例如:

ADR R0,exit ;标号exit 处的地址装入R0中 BX R0 ;跳转到exit 处

3.3 数据传送指令

ARM 数据处理方向和数据源

ARM 只有两种数据传送:存储和加载

寄存器R0~R15 存储器 存储

加载 ARM 处理器 外围模块或芯片 存储指令:STR 加载指令:LDR

ARM经典汇编程序

1冒泡排序的ARM汇编程序ORG 09B0H QUE:MOV R3,#50H QUE1:MOV A,R3 MOV R0,A MOV R7,#0AH CLR 00H MOV A,@R0 Q12:INC R0 MOV R2,A CLR C MOV 22H,@R0 CJNE A,22H,Q13 SETB C Q13:MOV A,R2 JC Q11 SETB 00H XCH A,@R0 DEC R0 XCH A,@R0 INC R0 Q11:MOV A,@R0 DJNZ R7,Q12 JB 00H,QUE1 SJMP $ END

2 ARM汇编希尔排序法对10个带符号数进行排序Code: void shell(int src[],int l,int r){ int ih; r++; for(ih=1;ih<(r-l)/9;ih=ih*3+1); //eax,ih //ebx,il //ecx,ir //edx,cmps _asm{ push eax push ebx push ecx push edx push esi push edi;貌似这堆进栈用处不大哎 mov edi,src mov eax,dword ptr [ih] LIH: cmp eax,0 jna EXIH mov ebx,eax dec ebx LLH: cmp ebx,dword ptr [r] jnb EXLLH mov ecx,ebx mov edx,dword ptr [edi+ecx*4]

LCMP: mov esi,eax dec esi cmp ecx,esi jna EXCMP push ecx sub ecx,eax cmp edx,dword ptr [edi+ecx*4] pop ecx jnb EXCMP push ebx push ecx sub ecx,eax mov ebx,dword ptr [edi+ecx*4] pop ecx mov dword ptr [edi+ecx*4],ebx pop ebx sub ecx,eax jmp LCMP EXCMP: mov dword ptr [edi+ecx*4],edx inc ebx jmp LLH EXLLH: push ecx mov ecx,3 push edx cdq

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/138626206.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/138626206.html,/u/31996/showart.php?id=326146 3. ARM GNU 汇编伪指令简介,https://www.doczj.com/doc/138626206.html,/jb8164/archive/2008/01/22/41661.aspx 4. GNU汇编使用经验,https://www.doczj.com/doc/138626206.html,/u1/37614/showart_39009 5.html 5. GNU的编译器和开发工具,https://www.doczj.com/doc/138626206.html,/blog-htm-do-showone-uid-34335-itemid-81387-type-blog.html 6. 用GNU工具开发基于ARM的嵌入式系统,https://www.doczj.com/doc/138626206.html,/liren0@126/blog/static/32897598200821211144696/ 7. objcopy命令介绍,https://www.doczj.com/doc/138626206.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

ARM汇编语言和C_C_语言混合编程的方法_史斌

嵌入式技术 电 子 测 量 技 术 ELECT RO NIC M EA SU REM EN T T ECHN O LO G Y 第29卷第6期 2006年12月  ARM汇编语言和C/C++语言混合编程的方法 史斌 (天津大学电子信息工程学院天津300072) 摘 要:文中首先对在嵌入式系统设计中广泛应用的A RM系列微处理器做了简要介绍;接着详细阐述了基于A RM 核的嵌入式微处理器的汇编语言和C/C++语言混合编程的方法:包括代码简洁而功能有限的在线汇编技术和功能强大、基于模块化设计的A T PCS规则;最后给出了详细的示例代码和分析。 关键词:嵌入式系统;A RM;汇编语言;在线汇编;A T PCS规则 Programming of ARM with both assembly and C/C++language Shi Bin (S chool of Electronic&Information Engin eering Tianjin University,Tianjin300072) A bstract:T his article briefly introduced A RM serial micropro ce sso r,w hich is ex tensiv ely used in embedded sy stem desig n;and then g ave the tw o metho ds of A RM-cor e embedded processor prog ramming with both assembly and C/C++ Language including in-line assembly w hich is co mpact but have so me limits and A T PCS rules w hich are pow erful and mo dularized.A t last,the re is some source code w ith analy sis for demo nstra tion. Keywords:embedded sy stem;A RM;assembly;in-line assembly;A T PCS 0 引 言 A RM是一种高性能、低功耗的32位RISC嵌入式处理器系列。目前在各种嵌入式系统中A RM获得了广泛的应用。 A RM编程可以使用汇编语言和C/C++语言,使用汇编语言编程目标代码效率较高,但较为繁琐,设计大型系统时不易维护;而C/C++语言比较简洁明了,但代码效率即使经过优化,也比汇编语言低,特别是在一些实时性强和需要精细处理的场合,C/C++语言难以胜任。因此一个折中的办法是:使用C/C++语言写整体框架,而使用汇编语言实现局部模块,这就涉及到汇编语言和C/C ++语言混合编程的问题。为此本文介绍了在ADS中常用的2种汇编语言和C/C++语言混合编程方法:在线汇编(in-line assem bly)和AT PCS(A RM-T humb Produce C all S tandard)规则。 1 在线汇编(in-line as sembly) 在线汇编的具体含义就是:在C/C++代码中插入一段汇编代码,以实现某种C/C++无法达到的效果,例如: { INTM SK=0xfffff fff;//屏蔽所有的向量中断, C/C++代码 __asm//插入一段汇编代码 { M RS r0,CPS R;//将状态积存器的内容传递到r0 ORR R0,R0,0x000000C0;//通过或运算将r0的第6,7两位置1,其它位不变 M SR CPSR_c,r0;//将r0的低8位送到CPS R的低8位,以屏蔽FIQ中断 } IN TPND=0xfffff fff;//清除全部中断标志位, C/C++代码 } 因为CPS R是一个物理寄存器,没有存储器的I/O映射,而A RM的C/C++语言使用的是ANSI标准,不像KeilC51那样有诸如sbit和sfr的扩展,所以访问C PS R的唯一方法就是用汇编语言;通过在C/C++代码中插入一段简短的汇编代码,来实现对CPSR的访问。再比如一些波形发生的场合,需要每隔一段精确的时间向端口送数据,那么C/C++代码经编译后产生的指令数是无法预知的,所以无法实现精确定时,因此就要使用在线汇编。 在线汇编通过__asm关键字实现,一般格式为: ……//C/C++代码 __asm { 指令1;指令2;指令3;…… 89

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

汇编语言中常用的伪指令 分类:软件相关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.存储器访问指令 LDR STR LDR Load 32-bit word to Memory. Syntax LDR{cond} Rd, [Rn] LDR{cond} Rd, [Rn, offset] LDR{cond} Rd, [Rn, offset]! LDR{cond} Rd, label LDR{cond} Rd, [Rn], offset Description LDR{cond} Rd, [Rn] (zero offset) Rn is used as address value. LDR{cond} Rd, [Rn, offset] (Pre-indexed offset) Rn and offset are added and used as address value. LDR{cond} Rd, [Rn, offset]{!} (Pre-indexed offset with update) Rn and offset are added and used as address value. The new address value is written to Rn. LDR{cond} Rd, label (Program-relative) The assembler calculates the PC offset and generates LDR{cond} Rd, [R15, offset]. LDR{cond} Rd, [Rn], offset (Post-indexed offset) Rn is used as address value. After memory transfer, the offset is added to Rn. Example LDR R8,[R10] //loads r8 from the address in r10. LDRNE R2,[R5,#960]! //(conditionally) loads r2 from a word 960 bytes above the address in r5, and increments r5 by 960. LDR R0,localdata //loads a word located at label localdata STR Store register 32-bit words to Memory. The address must be 32-bit word-aligned. Syntax STR{cond} Rd, [Rn] STR{cond} Rd, [Rn, offset] STR{cond} Rd, [Rn, offset]! STR{cond} Rd, label

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