linux 嵌入式汇编 adc,嵌入式Linux ARM汇编(四)——ARM汇编程序设计

嵌入式Linux ARM汇编(四)——ARM汇编程序设计

汇编程序有顺序、循环、分支、子程序四种结构形式。

一、顺序结构

程序实例:

AREA Buf,DATA,READWRITE;定义数据段Buf

ArrayDCB 0x11,0x22,0x33,0x44;定义12个字节的数组Array

DCB 0x55,0x66,0x77,0x88

DCB 0x00,0x00,0x00,0x00

AREA hello,CODE32,READONLY

ENTRY

LDR R0,=Array;取得数组Array的首地址

LDR R2,[R0];装载数组第1字节数据给R2

MOV R1,#1

LDR R3,[R0,R1,LSL#2];装载数组第5字节数据给R3

ADD R2,R2,R3

MOV R1,#8

STR R2,[R0,R1,LSL#2];

END

二、分支结构

1、ifelse分支结构的程序实现

C语言实现:

int x=76;

int y=88;

if(x>y)

z=100;

else

z=50

ARM汇编语言实现

MOV R0,#76;初始化R0的值

MOV R1,#88;初始化R1的值

CMP R0,R1;判断R0>R1?

MOVHI R2,100;R0>R1时,R2=100

MOVLS R1,50;R0

2、B指令实现散转功能

CMPR0,#MAX_INDEX;判断索引号是否超出最大索引值

ADDLOPC,PC,R0,LSL#2;索引号若没有超出,则程序跳到相应位置

BHIERROR;索引号若超出,则进行出错处理

BFUN1;跳到第一个程序

BFUN2;跳到第二个程序

BFUN3;跳到第三个程序

三、循环结构

1、for循环

C语言实现:

for(i = 0; i < 10; i++)

x++;

ARM汇编语言实现:

R0为x,R2为i,均为无符号整数

MOV R0,#0;初始化R0=0

MOV R2,#0;初始化R2=0

FORCMP R2,#10;判断R2<10?

BCS FOR_E;若条件失败(即R>=10),退出循环

ADD R0,R0,#1;执行循环体,R0=R0+1

ADD R2,R2,#1;R2=R2+1

BFOR

FOR_E

2、wihle循环

C语言实现:

while(x<=y)

X*=2;

ARM汇编语言实现:

x为R0,y为R1,均为无符号整数

MOVR0,#1;初始化R0=1

MOVR1,#20;初始化R1=20

BW_2;首先要判断条件

W_1MOVR0,R0,LSL#1;循环体,R0*=2

W_2CMPR0,R1;判断R0<=R1,即x<=y

BLSW_1;若R0<=R1,继续循环体

W_END

3、循环语句实现数据块的复制

ARM汇编语言实现:

LDRR0,=DATA_DST;指向数据目标地址

LDRR1,=DATA_SRC;指向数据源地址

MOVR10,#20;复制数据个数20*N个字

;N为LDM指令操作数据个数

LOOPLDMIAR1!,{R2-R9};从数据源读取8个字节到R2-R9

STMIAR0!,{R2-R9};将R2-R9的数据保存到目标地址

SUBSR10,R10,#1;R0-1,并改变程序状态寄存器

BNELOOP

4、双层for循环的实现

ARM汇编语言实现:

AREABlock,CODE; 声明代码段

ENTRY

;for(i = 0; i < 10; i++)

;for(j = i+1; j<=10; j++)

;z +=1

START

MOV R1, #0; i = 0

MOV R0, #0; Z

LOOP

CMP R1, #10; i < 10

BEQ STOP

ADD R2, R1, #1; j = i+1

LOOP1

CMP R2, #10+1; j<=10

ADDNE R0, R0, #1; z +=1

ADDNE R2, R2, #1; j++

BNE LOOP1

ADD R1, R1, #1;  i++

B LOOP

STOP

MOV R0, #0x18

LDR R1, =0x20026

SWI 0x123456

END

5、数据块拷贝

ARM汇编语言实现:

;数据块拷贝,利用LDR/STR指令

num EQU10

AREABlockData,DATA; 声明数据段

srcDCD0,1,2,3,4,5,6,7,8,9; 定义十个数

dstSPACE10*4

AREABlock,CODE; 声明代码段

ENTRY

START

LDRR1, =src

LDR R2, =dst

MOV R3, #num

LOOP

LDR R0, [R1], #4

STR R0, [R2], #4

SUBS R3, R3, #1

BNE LOOP

STOP

MOV R0, #0x18

LDR R1, =0x20026

SWI 0x123456

END

四、子程序

调用程序在调用子程序时,经常需要传送一些参数给子程序,子程序运行完成后也需要回送结果给调用程序。调用程序和子程序之间的信息传送称为参数传送。参数传送的两种方法:

A、当参数比较少时,可以通过寄存器传送参数

B、当参数比较多时,可以通过内存块或堆栈传送参数

调用程序在调入子程序时必须保存正确的返回地址,即当前PC值,PC值可以保存在专用的寄存器R14中,也可以保存到堆栈中。根据这两种情况,可以在子程序采用如下的返回语句:

MOV PC,LR;恢复PC的值

STMFD SP!,{R0-R7,PC};将PC值从堆栈中返回

使用堆栈来恢复处理器的状态时,STMFD与LDMFD要配合使用。

一般来说,在ARM汇编语言程序中,子程序的调用是通过B来实现的。BL在执行时完成如下操作:

将子程序的返回地址存放在链接寄存器LR中,同时将程序计数器PC指向子程序的入口点,当子程序执行完毕需要返回调用处时,只需要将存放在LR中的返回地址重新拷贝给程序计数器PC即可。

C语言实现:

int MAX(int i, int j)

{

if(x > j)

return i;

else

return j;

}

int main(void)

{

int a, b, c;

a = 19;

b = 20;

c = MAX(a, b);

}

ARM汇编语言实现:

XEQU19;定义X的值为19

NEQU20;定义N的值为20

AREA hello,CODE32,READONLY;声明代码段

ENTRY;标识程序入口

STARTLDR R0,=X;给R0,R1赋初值

LDR R1,=N

BL MAX;调用子程序MAX

HALTBHALT;死循环

MAX;声明子程序MAX

CMP R0,R1

MOVHI R2,R0;比较R0,R1,R2等于最大值

MOVLS R2,R1

MOV PC,LR;返回语句

MAX_END

END

五、常见程序设计示例

以下是几个类似C语言编程题目的例子,用ARM汇编语言给出的程序。

1、存储器从0x400000开始的100个单元中存放着ASCII码,编写程序,将其所有的小写字母转换成大写字母,对其它的ASCII码不做变换。

MOVR0,#0x400000

MOVR1,#0

LP

LDRBR2,[R0,R1]

CMPR2,#0x61

BLONEXT

CMPR2,#0x7B;0x61---0x7A为小写字母的ASC

SUBLOR2,R2,#0x20

STRBLOR2,[R0,R1]

NEXT

ADDR1,R1,#1

CMPR1,#100

BNELP

2、编写一简单ARM汇编程序段,实现1+2+…+100的运算

MOVR2,#100

MOVR1,#0

LOOP

ADDR1,R1,R2;R1中为累加和

SUBSR2,R2,#1;R2控制循环

BNELOOP

3、编写程序,比较存储器中0x400000和0x400004两无符号字数据的大小,并且将比较结果存于0x400008的字中,若两数相等其结果记为0,若前者大于后者其结果记为1,若前者小于后者其结果记为-1

MOVR0,#0x400000

LDRR1,[R0];取第1个数

LDRR2,[R0,#4];取第2个数

CMPR1,R2;两个数相比较

MOVHIR1,#1;R1大

MOVLOR1,# -1;R1小

MOVEQR1,#0;两个数相等

STRR1,[R0,#8]

4、编写一程序,存储器中从0x400200开始有一个64位数。(1)将取反,再存回原处;(2)求其补码,存放到0x400208处

LDRR0,=0x400200

LDRR2,=0xFFFFFFFF

LDRR1,[R0];取低32位数

EORR1,R1,R2;取反

STRR1,[R0];存低32位反码

ADDSR1,R1,#1;又加1为求补

STRR1,[R0,#8];存低32位补码

LDRR1,[R0,#4];取高32位数

EORR1,R1,R2;取反

STRR1,[R0,#4];存高32位反码

ADCR1,R1,#0;高32位求补

STRR1,[R0,#12];存高32位补码

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值