嵌入式:arm汇编语言程序设计基础教程

author author     2022-12-31     245

关键词:

汇编语言程序设计的步骤

① 合理地分配存储器资源,将前述的目标系统‘数据结构模型’表示到各存储器单元。

② CPU寄存器数量有限,在程序中,大多数操作都要使用寄存器;并且有的操作使用特定的寄存器(如堆栈操作使用SP/R13等),程序中要合理分配各寄存器的用途。

用计算机语言,对数据结构模型和流程图表示的算法进行准确地描述。

① 语法调试:排除程序中的语法错误。

② 功能调试:保证程序的逻辑功能正确性。

用文档形式记录说明程序的功能、使用方法、程序结构、算法流程等每一个阶段的工作。 把解题的方法、步骤用框图形式表示。如果问题比较复杂,那么可以逐步细化,直到每一框图可以容易编程为止。流程图不仅便于程序的编制,且对程序逻辑正确性也比较容易查找和修改。

顺序程序设计

顺序程序是一种最简单的程序结构,也称为直线程序,它的执行自始自终按照语句的先后顺序进行。这种结构的流程图,除了有一个起始框,一个终止框外,就是若干执行框。

例:试编制一程序,完成10+3的操作。

嵌入式:ARM汇编语言程序设计基础教程_寄存器

AREA  ARMex, CODE, READONLY ; 代码段名ARMex
ENTRY ; 程序的入口
CODE 32

start
MOV R0, #10 ; 将立即数10存入寄存器R0
MOV R1, #3 ; 将立即数3存入寄存器R1
ADD R0, R0, R1 ; R0 = R0 + R1
stop
MOV R0, #0x18 ; 这三条指令是ADS调试环境特约
LDR R1, =0x20026 ;程序运行结束返回编译器调试环境
SWI 0x123456

END ; 结束

分支程序设计

许多实际问题需要根据不同的情况作出不同的处理。在程序中,针对不同的情况把不同的处理方法编制成各自的处理程序段,运行时由机器根据当时的条件自动作出判断,选择执行相应的处理程序段。这样的程序结构中,计算机不再完全按指令存储的顺序执行,称之为分支。分支程序使用转移指令B、子程序调用指令BL或带状态转移指令BX来实现。

例:给定以下符号函数:

嵌入式:ARM汇编语言程序设计基础教程_子程序_02

任意给定值,假定为-25,存放在x单元,函数值存放在y单元;要求根据x中的值来确定y的值。

嵌入式:ARM汇编语言程序设计基础教程_循环程序_03

AREA symbol, CODE, READONLY ; 代码段的名字 symbol

ENTRY ; 程序的入口

CODE32

start

LDR R0, =x ; 加载数据段中的变量x地址,存入R0

LDR R1, =y ; 加载数据段中的变量y地址,存入R1

LDR R2, [R0] ; 加载变量x的值,存入R2

compare

CMP R2, #0 ; 将R2的值与0作比较

BEQ ZERO ; 如果R2等于0,那么转向标号ZERO处

BGT PLUS ; 如果R2大于0,那么转向标号PLUS处

MOV R3, #-1 ; 否则,R2小于0,将-1存入R3中

B stop

ZERO

MOV R3, #0 ; R2等于0,将0存入R3中

B stop

PLUS

MOV R3, #1 ; R2大于0,将1存入R3中

; 续上段代码

stop

STR R3, [R1]

MOV R0, #0x18

LDR R1, =0x20026

SWI 0x123456

AREA Data, DATA, READWRITE

x DCD -25

y DCD 0

END

循环程序设计

顺序程序和分支程序中的指令每次运行最多只执行一次。在实际应用中重复地做某些事的情况很多,这也是计算机最擅长的工作方式。重复地执行某些指令,最好用循环程序来实现。
循环程序的结构---重复地执行同一种运算,直到某种条件满足。

建立循环初始值。如设置地址指针、计数器、其他循环参数的起始值等。循环程序的主体业务代码,可以是一个顺序程序、分支程序或另一个循环程序。 为执行下一个循环而修改某些参数,尤其循环控制变量的修改等。

条件控制循环:通过判断循环终止条件是否已成立,控制循环。判断循环结束条件是否成立,决定是否继续循环。

例如:计数控制循环;通过计数循环次数,判断是否已达到预定次数,控制循环。对循环结束进行适当处理;有的循环程序可以没有这部分。

用计数控制循环适用于已知循环次数的循环程序设计

例:从x单元开始的30个连续字单元中存放有30个无符号数,从中找出最大者送入y单元中。

嵌入式:ARM汇编语言程序设计基础教程_子程序_04

分析:

根据题意,把第一个数先送入Rx寄存器,将Rx中的数与后面的29个数逐个进行比较,如果Rx中的数较小,则将该较大的数送入Rx ;继续与余下的数据逐个比较。在比较过程中, Rx中始终保持较大的数,共计比较29次,则最终Rx中保留了最大数,最后把Rx中的数(最大者)送入y单元。

AREA  max, CODE, READONLY   ; 代码段的名字 max
ENTRY ; 程序的入口
CODE32
num EQU 29 ; 比较的次数
start
LDR R0, =x ; R0指向源数据块x
LDR R1, =y ; R1指向单元y
LDR R2, =num ; R2作为计数器
LDR R3, [R0] ; 将源数据块x中第一个数加载到R3中
compare
ADD R0, R0, #4 ; 每进行一次比较,将R0指针地址加4
LDR R4, [R0] ; 依次将源数据块x中下一个数加载到R4中
CMP R3, R4 ; 比较R3和R4中数的大小
MOVCC R3, R4 ; 如果R3小于R4,则将较大的数送入R3中
SUBS R2, R2, #1 ; 计数器值减1
BNE compare ; 如果不为0,那么继续跳到compare执行
STREQ R3, [R1] ; 如果为0,那么循环比较结束,R3是最大的数
; 并且将R3中的数加载到R1指向的单元(即y)中


stop
MOV r0, #0x18
LDR r1, =0x20026
SWI 0x123456

AREA Data, DATA, READWRITE
x DCD 73,59,61,34,81,107,225,231,54,43
DCD 100,35,1,42,222,254,34,71,100,31
DCD 33,119,13,44,18,147,55,244,97,3
y DCD 0
END

② 适用于已知循环条件的循环程序设计

适用于无法确定循环次数,但知道循环结束的条件

例:从自然数1开始累加,直到累加和大于1000为止,统计被累加的自然数的个数,并把统计的个数送入n单元,把累加和送入sum单元。

分析:

根据题意,被累加的自然数的个数事先未知,因此不能用计数方法控制循环。但题目中给定一个条件,即累加和大于1000则停止累加,因此,可以根据这一条件控制循环。我们用R3寄存器放累加和,用R4寄存器放每次取得的自然数,其中它的值也是统计自然数的个数。

嵌入式:ARM汇编语言程序设计基础教程_分支程序_05

AREA  SUM, CODE, READONLY ; 代码段的名字 SUM
ENTRY ; 程序的入口
CODE32
start
LDR R0, =n ; 将数据段中自然数的个数n的地址加载到R0寄存器
LDR R1, =sum ; 将数据段中自然数的累加和sum的地址加载到R1寄存器
LDR R3, =0 ; R3存放自然数的累加和
LDR R4, =0 ; R4用于循环个数的统计/每次取得的自然数
LDR R5, =1000 ; R5用于循环结束的界限值
continue
ADD R4, R4, #1 ; 取下一个自然数
ADD R3, R3, R4 ; 累加自然数
CMP R3, R5 ; 比较累加和是否超过了1000
BCC continue ; 如果小于1000,那么跳到compare执行
STRCS R3, [R1] ; 如果大于1000,那么将累加和存储到R1所指向的单元中
STRCS R4, [R0] ; 如果大于1000,那么将已累加的自然数个数值存储
; 到R0所指向的单元中


stop
MOV r0, #0x18
LDR r1, =0x20026
SWI 0x123456

AREA Data, DATA, READWRITE
n DCD 0 ; 定义累加的自然数的个数
sum DCD 0 ; 定义自然数的累加和

END

子程序设计

子程序概念

如果在一个程序中的多处用到同一段程序代码,那么可以把这段共同的程序代码抽取出来,写成一个相对独立的程序段,每当需要执行这段代码时,就调用这个程序段,执行完这个程序段后,再返回原来调用它的程序。这样编写程序时,就不必重复写这段代码了,而这样的程序段称为子程序或子过程。

子程序的调用与返回

主程序中使用BL指令实现子程序的调用

BL 子程序名

在子程序结束处,使用如下指令返回到主程序中。

MOV PC, LR

主程序与子程序之间的参数传递

主程序调用子程序时,可以向子程序传递一些参数;同样,子程序运行后也可把一些结果参数传回给主程序。主程序与子程序之间的这种信息传递称为参数传递。

三种参数传递方式

  1. 寄存器传递参数方式
  2. 存储区域传递参数方式
  3. 堆栈传递参数方式

寄存器传递参数方式

例:用子程序实现内存区里的字符串拷贝功能,即将存储单元中源字符串对应拷贝到目的字符串中。

技术思想:主程序将待传递的数据直接写入约定的通用寄存器,在子程序中直接使用;或子程序返回后,主程序直接从约定的通用寄存器中获得子程序的结果数据。

应用特点:这种方式适合于传递较少参数的应用场合。

解题思路:

通过设定两个地址指针,分别指向存储区中的源字符串和目的字符串;然后通过加载和存储指令(LDR和STR)的寄存器间接寻址方式,依次从源字符串读取一个字符数据,写入到目的字符串的对应字符位置中,直到遇到源字符串的结束标志’\\0’为止。

AREA    StrCopy, CODE, READONLY
ENTRY
CODE32
start
LDR R1, =srcstr ; R1指向数据区的源字符串
LDR R0, =dststr ; R0指向数据区的目的字符串
BL strcopy ; 调用子程序strcopy,完成字符串拷贝
stop
MOV R0, #0x18 ; 程序结束返回编译器调试环境
LDR R1, =0x20026
SWI 0x123456
strcopy
LDRB R2, [R1], #1 ; 将R1指向的单元内容加载到R2中
STRB R2, [R0], #1 ; 将R2中的数存储到R0指向的单元中
CMP R2, #0 ; 检查R0的值是否等于0
BNE strcopy ; 如果不等于0,那么转到strcopy处执行
MOV PC, LR ; 子程序返回


AREA Strings, DATA, READWRITE
srcstr DCB "First string - source",0 ; 源字符串
dststr DCB "Second string - destination",0 ; 目的字符串
END

存储区域传递参数方式

例:通过设置的入口参数查找函数地址表,实现选择不同的函数功能。

说明:本题中通过事先将函数地址存放在存储单元中,通过查找地址表的方法,实现根据“选择项(choice)”进入不同的函数体功能。

技术思想:主程序和子程序约定了某一共享内存块用于参数传递,主程序在BL调用子程序前,先将要传递的参数写入到约定的存储单元,子程序可从约定的内存读取这些参数;子程序返回时,也可以使用该方式将数据传给主程序。

应用特点:这种方式可以传递大批量数据。

实现方法:当主程序与子程序有较多的数据需要传递时,可以通过共享内存区或传内存数据块地址方式来传递批量数据。

通过伪指令ADR直接装载近距离数据块地址;

通过伪指令ADRL直接装载中距离数据块地址;

通过语句LDR Rd, =Label转载远距离的数据块地址;

AREA    Jump, CODE, READONLY
num EQU 4 ; 函数地址表内容的个数
ENTRY
CODE32
start
LDR R0, =choice ; R0指向存储区的choice单元
LDR R0, [R0] ; 设置第一个参数:选择执行哪一个函数
MOV R1, #16 ; 设置第1个操作数
MOV R2, #2 ; 设置第2个操作数
BL arithfunc ; 调用子程序arithfunc
stop
MOV R0, #0x18 ; 程序结束返回编译器调试环境
LDR R1, =0x20026
SWI 0x123456
arithfunc
CMP R0, #num ; 比较R0的值是否超过函数地址表的个数
MOVHS PC, LR ; 如果大于,那么就返回到标号stop处
ADR R3, JumpTable ; 将函数地址表的地址作为基地址
LDR PC, [R3, R0, LSL #2] ; 根据R0参数进入对应的子程序


JumpTable ; 函数地址表的入口基地址
DCD DoAdd ; 加法子程序
DCD DoSub ; 减法子程序
DCD DoMul ; 乘法子程序
DCD DoDiv ; 除法子程序
DoAdd
ADD R0, R1, R2 ; R0 = R1 + R2
MOV PC, LR ; 返回
DoSub
SUB R0, R1, R2 ; R0 = R1 - R2
MOV PC, LR ; 返回
DoMul
MOV R0, R1, LSL R2 ; R0 = R1 << R2
MOV PC, LR ; 返回
DoDiv
MOV R0, R1, LSR R2 ; R0 = R1 >> R2
MOV PC, LR ; 返回
AREA NUM, DATA, READWRITE
choice DCD 3 ; 0:表示选择加法子程序 1:表示选择减法子程序
; 2:表示选择乘法子程序 3:表示选择除法子程序
END

堆栈传递参数方式

主程序和子程序使用同一个堆栈,主程序在BL调用子程序前,先将要传递的参数压入到堆栈中,子程序可从堆栈中读取传过来的数据;子程序返回需要向主程序传递参数时,也可使用此方法。

参考文献:

孟祥莲.嵌入式系统原理及应用教程(第2版)[M].北京:清华大学出版社,2017.

嵌入式编程入门教程,学习设计嵌入式工程师

...了。不知道自己究竟从哪里开始?下面就跟着我学习设计嵌入式工程师的修炼日记吧!简单说,从arm基础知识到裸机编程,从uCOSII到linux,从linux基础的命令到shell编程,从u-boot到文件系统,最后 查看详情

嵌入式:arm符号定义伪操作详解

ARM汇编语言的伪操作、宏指令与伪指令ARM汇编语言源程序中语句一般由指令、伪操作、宏指令和伪指令组成伪操作是ARM汇编语言程序里的一些特殊指令助记符,它的作用主要是为完成汇编程序做各种准备工作,在源程序进行汇编... 查看详情

嵌入式开发工程师学习线路

 一、核心学习课程  1、应用软件基础      Linux基础      C语言  2、底层驱动程序开发      ARM编程(ARM体系结构、ARM汇编、开发板常见的外设裸机编程)      Linux驱动开发二、Android扩展... 查看详情

完整的嵌入式学习路线是怎样的?

嵌入式开发学习有相关的路线和课程,一步一步打好基础,进入到实际开发阶段才不会茫然失措。要学习编程语言、软硬件基储计算机系统、电子控制相关的的、知识等等,下面整理了嵌入式开发的学习方式,仅供参考!1、c\\c+... 查看详情

嵌入式开发工程师学习线路图

一、核心学习课程  1、应用软件基础      Linux基础      C语言  2、底层驱动程序开发      ARM编程(ARM体系结构、ARM汇编、开发板常见的外设裸机编程)      Linux驱动开发二、Android扩展  ... 查看详情

arm汇编基础详解(代码片段)

...跳转指令2.5算术运算指令2.6逻辑运算指令前言我们在进行嵌入式Linux开发的时候是绝对要掌握基本的ARM汇编,因为Cortex-A芯片一上电SP指针还没初始化,C环境还没准备好,所以肯 查看详情

嵌入式:arm内嵌汇编及c和arm汇编相互调用

...不能直接引用C的变量定义,数据交换必须通过ATPCS进行。嵌入式汇编在形式上表现为独立定义的函数体。内嵌汇编 查看详情

ios汇编入门教程arm64汇编基础(代码片段)

__attribute__anti_debug__arm64____asm____volatile__testabresabresmainrestesthelloBBspspstrw0strw1ldrw0ldrw1addw0w0w1strw0ldrw0addspspretBBspspstpx29x30addx29sporrw0wzrorrw1wzrsturwzrbl_testmovw1strw0m 查看详情

arm基础教程|armcortex-m与armv8-m什么关系?

...众号,不错过精彩内容作者|strongerHuang微信公众号 | 嵌入式专栏我们使用的处理器都有一套架构,比如intel酷睿i5属于X86架构,再比如STM32F0是Cortex-M0内核,属于ARMv6-M架构。现在的技术一代比一代强,你对ARM处... 查看详情

基于arm的多路温度采集控制系统项目介绍

嵌入式项目实践–多路温度采集控制系统(1)项目介绍项目实践说明: 本实践项目是嵌入式开发培训(阶段1)基础应用开发视频课程的综合实践项目。 项目开发使用的技术知识点包括:C语言编程,文件编程,串口编程... 查看详情

xilinxzynq-7000嵌入式系统设计与实现学习教程

...性能算法处理。新的设计工具的推出,vivadoHLS,更加注重嵌入式系统的系统级建模,通过HLS工具,用户只需要编写C语言代码,就可以让工具自动转换和生成HDL代码随着异构架构和片上系统技术的不断发展,协同设计、协同仿真... 查看详情

《信息安全系统设计基础》实验五

《信息安全系统设计基础》实验五简单嵌入式WEB服务器实验班级:1452姓名:20415208蔡野20145235李涛20145230熊佳伟实验日期:2016.12.1时间:10:10-12:30实验序号:5实验目的:掌握在ARM开发板实现一个简单WEB服务器的过程。学习在ARM开... 查看详情

关于qt开发平台和arm嵌入式的关系。

...在此基础上接触一些心得东西,学习单片机我就是想进军嵌入式,看了一些嵌入式的招聘简介,很多公司要求会QT,我以前也接触过QT,用QT编译过C语言程序,我当时学C语言的时候,凡是可以编译的编译器,我都简单摸索了一下... 查看详情

嵌入式工程师认证怎么考?

...常见Flash原理与设计。第三阶段:Linux内核相关知识辅导嵌入式开发环境建立,Linux内核基础,字符设备,中断原理与应用,调试技术,U-Boot移植及内核移植。ATC考点:硅谷芯微科技园南区中心扩展资料;嵌入式系统是以应用为中... 查看详情

xilinxzynq-7000嵌入式系统设计与实现学习教程

...性能算法处理。新的设计工具的推出,vivadoHLS,更加注重嵌入式系统的系统级建模,通过HLS工具,用户只需要编写C语言代码,就可以让工具自动转换和生成HDL代码随着异构架构和片上系统技术的不断发展,协同设计、协同仿真... 查看详情

学习嵌入式stm32有必要吗,直接用arm开发板怎么样?

...设计有10多年的经验了,我来告诉你的困惑,你如果喜欢嵌入式设计的话你就学习STM32你如果喜欢处理器运算方面的话你就学习ARM11类的,其实你是想问,你应该学习微控制器还是微处理器。stm32是微控制器ARM11还有那些所谓的可... 查看详情

物联网工程师分享资料

...:https://bbs.usoftchina.com/thread-199892-1-1.html资料分别是:国嵌嵌入式培训达内C++全套视频(30多g)凌阳嵌入式嵌入式开发入门到精通基于QT平台的手持媒体播放器项目实战ARM移植串口通信ZigBee学习版视频嵌入式学习嵌入式实时操作系统UCO... 查看详情

arm汇编基础--ads1.2安装与第一个arm汇编程序

前言最近的工作是与逆向相关,用到ARM汇编,以前在大学时学过x86汇编和ARM开发,自我感觉当时学的还挺好,很久没用也生疏了.正好趁着这个机会也复习一下ARM汇编.关于ARM的介绍和理论知识,此处就不再赘述.进入正题:安装ADS1.2安装过... 查看详情