【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)

发布者:温馨生活最新更新时间:2024-10-18 来源: cnblogs关键字:ARM  汇编  伪指令  协处理器  访问指令 手机看文章 扫描二维码
随时随地手机看文章

一. ARM 汇编概述

1. 汇编使用位置


汇编位置 : 

-- 启动代码 : Bootloader 初始化时对 CPU 和 协处理器 等进行初始化, 此时没有建立起 C 语言运行环境, 这个时候使用汇编语言执行初始化操作;

-- 效率要求 : 汇编效率高, Linux 内核中, 对效率有特殊要求的地方需要汇编;


2. 汇编分类

(1) ARM 标准汇编


ARM 标准汇编简介 : 

-- 使用场景 : 适用于ARM公司的汇编器, 适合在 Windows 平台使用, 如ADS;


(2) GNU汇编

GNU 汇编简介 : 

-- 使用场景 : 适用于 Linux 平台交叉编译工具链的汇编器;


3. ARM 汇编程序框架

ARM 汇编框架 : 

-- ARM 汇编框架示例 : 


.section .data
	< 初始化的数据>
.section .bss
	< 未初始化的数据>
.section .text
.global _start
_start:
	<汇编代码>

-- 程序入口 : '_start:' 是汇编程序的入口, 相当于 main();


-- 标注入口 : 使用 '.global _start' 标注程序入口, 外部才可以识别这是程序入口;

-- 标明代码段 : '.section .text' 标明这是一个代码段;

-- 标明 bss 段 : 使用 '.section .bss' 标明bss段, 如果没有 bss 段 和 数据段, 直接从 .text 开始;


4. 搭建汇编开发调试环境

(1) 汇编程序准备


程序代码 : 

-- 定义代码段 : .text ;

-- 定义程序入口 : .globl _start;

-- 代码示例 : 


.text
.globl _start
_start:
	mov r1,#1
	mov r2,#2
	mov r3,#3


Makefile 代码 :

-- 链接 elf 格式文件 : 设置程序起始位置 6410板子是 0x50008000 地址;

-- 在 arm-linux-ld 指定程序起始地址 : 在 -Ttext 50008000 即可;

-- 如果使用链接器脚本指定地址 : 注意第三行指定程序起始地址;


SECTIONS
{
	. = 0x50008000;

	. = ALIGN(4);
	.text :
	{
		led.o	(.text)
		*(.text)
	}

	. = ALIGN(4);
	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

	. = ALIGN(4);
	.data : { *(.data) }


	. = ALIGN(4);
	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
}


-- 代码示例 : 


all:start.o
	arm-linux-ld -Ttext 0x50008000 -o start.elf $^

%.o:%.S
	arm-linux-gcc -g -o $@ $^ -c

clean:
	rm -rf *.o *.elf

(2) 启动 JLink 调试

JLink 调试启动 : 

-- 确保驱动安装 : 注意 要安装 Windows 驱动;

-- 连接 JLink : 虚拟机右下角连接 JLink;


-- 启动 JLinkGDBServer : 

[root@localhost JLink_Linux_V434a]# ./JLinkGDBServer 
SEGGER J-Link GDB Server V4.34a

JLinkARM.dll V4.34a (DLL compiled Aug 31 2011 11:51:40)

Listening on TCP/IP port 2331

J-Link connected
Firmware: J-Link ARM V8 compiled Aug 24 2011 17:23:32
Hardware: V8.00
S/N: 17935099
Feature(s): RDI,FlashDL,FlashBP,JFlash

J-Link found 2 JTAG devices, Total IRLen = 5
JTAG ID: 0x07B76F0F (ARM11)


(2) eclipse 调试环境


搭建 eclipse 调试环境 : 

-- 导入工程 : 选择 Makefile Project With Existing Code;


-- 选择导入的代码位置 : 


-- clean 代码 : 选择 'Project' --> 'Clean';


-- build 工程 : 选择 '菜单' --> Project --> Build All 选项即可;

-- 配置 Debug 调试参数 : 




-- 执行调试 : F6 单步调试走两步, 可以再 Register 视图中查看寄存器的值, 可以看到 r1 和 r2 被赋值为 1 和 2 了;



二. ARM 指令分类

ARM 汇编手册 : 



GNU 汇编 与 ARM 标准汇编区别 : 上面的手册是 ARM 标准汇编手册, 我们写的是 GNU 汇编手册, 有一定区别;

-- 大小写区别 : ARM 标准汇编 都是大写的, GNU 汇编可以是小写字母;


1. 算术和逻辑指令

(1) MOV 指令


MOV 指令简介 : 赋值操作;

-- 语法格式 : MOV , ;

-- 语法解析 : dest 是目的寄存器, op1 可以是立即数, 也可以是寄存器, 地址等, 等价于 dest = op1;


汇编程序注释 : 汇编中使用 '@' 符号添加注释;


示例代码 : 


.text
.global _start
_start:

@mov 指令范例
mov r1, #8	@将 8 赋值给 r1
mov r2, r1	@将 r1 中的值赋值给 r2
mov r3, #10	@将 10 赋值给 r3 寄存器


(2) MVN 指令


MVN 指令简介 : 取反赋值操作;

-- 语法格式 : MVN , ;

-- 语法解析 : 将操作数 op1 取反后 赋值给 dest;


指令示例 : 

-- 代码 : 


.text
.global _start
_start:

@mvn 指令范例
mvn r1, #0b10	@0b10 二进制数取反, 赋值给 r1
mvn r2, #5	@5 十进制数取反, 赋值给 r2
mvn r3, r1	@将 r1 寄存器的值, 赋值给 r3

(3) SUB 指令

SUB 指令简介 : 减法操作;

-- 语法格式 : SUB , , ;

-- 语法解析 : dest 存放减法结果, op1 是减数, op2 是被减数, dest = op1 - op2;

-- 注意 : dest op1 都不能使用立即数, op2 可以使用立即数;


代码示例 : 


.text
.global _start
_start:

@sub 指令范例
@sub r1, #4, #2 错误示例, 减数不能是立即数, 必须是寄存器
mov r2, #4
sub r1, r2, #4
mov r0, #1
sub r3, r1, r0

(4) ADD 指令


ADD 指令简介 : 加法操作;

-- 语法格式 : ADD , , ;

-- 语法解析 : dest 存放加法结果, op1 和 op2 是相加的两个数, dest = op1 + op2;

-- 注意 : dest op1 都不能使用立即数, op2 可以使用立即数;


代码示例 : 


@add 指令范例
mov r2, #1
add r1, r2, #3


(5) AND 指令


AND 指令简介 : 逻辑与操作;

-- 语法格式 : AND , , ;

-- 语法解析 : dest 存放逻辑与结果, op1 和 op2 是相与的两个数, dest = op1 & op2;

-- 注意 : dest op1 都不能使用立即数, 必须使用寄存器, op2 可以使用立即数;


代码示例 : 


.text
.global _start
_start:

@and 指令范例
mov r1, #5
and r2, r1, #0

mov r1, #5
mov r2, r1, #1


(6) BIC 指令

BIC 指令简介 : 位清除指令操作;

-- 语法格式 : AND , , ;

-- 语法解析 : dest 存放位清除结果, op1 是被清除的对象, op2 是掩码;

-- 示例 : 'bic r0, r0, #0b1011', 清除 r0 中的 第0, 1, 3 位, 其余位保持不变, 结果放入 r0 中;

-- 注意 : dest op1 都不能使用立即数, 必须使用寄存器, op2 可以使用立即数; 

-- 二进制表示 : 掩码中 % 在标准汇编中表示二进制, 但是在 GNU 汇编中无法使用, GNU 汇编中使用 0b 代表二进制;


代码示例 : 


.text
.global _start
_start:

@bic 指令范例
mov r1, #0b101011
bic r2, r1, #0b101	@将r1 的 0, 2 位清除

2. 比较指令

(1) CMP 指令


CMP 指令简介 : 比较指令;

-- 语法格式 : CMP , ;

-- 语法解析 : 比较结果有三种 op1 > op2 (CPSR N = 0), op1 = op2 (CPSR Z = 1), op1 < op2 (CPSR N = 1), 结果放入 CPSR 寄存器;


代码示例 : 


.text
.global _start
_start:

@cmp 指令范例
mov r1, #2
cmp r1, #1

mov r1, #2
cmp r1, #3

mov r1, #2
cmp r1, #2

(2) TST 指令


TST 指令简介 : 比较指令;

-- 语法格式 : TST , ;

-- 语法解析 : op1 和 op2 按位与操作, 结果影响 CPSR 寄存器, 如果结果 不为 0, CPSR 的 Z = 0, 如果结果为0, Z = 1;


代码示例 : 


.text
.global _start
_start:

@cmp 指令范例
mov r1, #0b101
tst r1, #0b001	@按位与结果是 0b1, 结果不为0, CPSR Z = 0

mov r1, #0b101
tst r1, #0b10	@按位与结果是 0, 结果不为

3. 分支指令


(1) B 指令


B 指令简介 : 分支指令;

-- 语法格式 : B{条件} 地址;

-- 语法解析 : 如果满足条件, 就跳转到 地址 位置, 如果不满足条件, 就执行下面的语句, 如果没有条件, 就是 100% 执行;;


代码示例 : 

-- 条件分析 : gt 是大于条件, 如果 r1 > r2 就走条件分支, 否则就继续执行下一条;


.text

.global _start

_start:


@b 分支指令范例

mov r1, #6

mov r2, #5

cmp r1, r2 @比较 r1 和 r2 中的值

@b 后可以跟一个条件, {条件} 在 {} 中就是可加可不加, 如果没有条件就是无条件100%执行

@gt 是大于条件指令, 如果条件满足会跳转到 branch1, 如果不满足就执行下面的指令

bgt branch1

add r3, r1, r2

b end @这里为了不执行 branch1 操作, 直接跳转到 end 执行


branch1:

sub r3, r1, r2


end:

nop


(2) BL 指令

BL 指令简介 : 带连接的分支指令;

-- 语法格式 : BL{条件} 地址;

-- 语法解析 : 如果满足条件, 就跳转到 地址 位置, 如果不满足条件, 就执行下面的语句, 如果没有条件, 就是 100% 执行;;


代码示例 : 


.text

.global _start

_start:


@bl 带连接的分支指令范例

mov r1, #2

cmp r1, #1

@此时跳转到 func1, func1 执行完程序无法返回, 如果 使用 bl 跳转, 程序会返回

@b func1

@此时使用 bl 跳转到 func1 执行, func1 执行完毕后会返回执行下面的语句

bl func1


mov r1, #2

cmp r1, #3


func1:

mov r1, #2

cmp r1, #2


mov r1, #4

cmp r1, #6


4. 移位指令


(1) LSL 指令


LSL 指令简介 : 逻辑左移指令;

-- 语法格式 : Rx, LSL#2;

-- 语法解析 : 将 Rx 寄存器中的值, 左移2 位;


代码示例 :


.text
.global _start
_start:

@lsl 左移指令范例
mov r1, #0b1
@将 r1 中的值, 左移 2 位, 放入 r1 寄存器中
mov r1, r1, lsl#2

(2) ROR 指令

ROR 指令简介 : 循环右移指令;

-- 语法格式 : Rx, ROR#2;

-- 语法解析 : 将 Rx 寄存器中的值 循环右移 2 位;


代码示例 : 


.text
.global _start
_start:

@ror 循环右移指令范例
mov r1, #0b11
@结果是 ob1000...0001
mov r1, r1, ror#1


5. 程序状态字访问指令


程序状态字 : CPSR 和 SPSR;

-- 注意 : 程序状态字 不能使用 通用寄存器的语句 如 MOV 等访问, 必须使用 程序状态寄存器的 专用指令 读写;


代码示例 : 


.text
.global _start
_start:

@mrs 指令范例
@rs 是 将 s -> r, sr 是 r -> s
mrs r0, cpsr	@将 cpsr 中的数据搬移到 r0 中
orr r0, #0b100	@将 cpsr 中的第三位置为1
msr cprs, r0

6. 存储器访问指令

(1) STR 指令


STR 指令简介 : 将 寄存器中的值 保存到 内存中;

-- 语法格式 : str r0, 地址;

-- 语法解析 : 将 R0 寄存器中的值 保存到 内存地址中;;


代码示例 : 


.text
.global _start
_start:

@str 指令范例
mov r0, #0xff
@将 r1 值改为 50000000 (OK-6410)
str r0, [r1]


-- 调试 : 添加地址监控, 在 Memory 视图中进行监控;

(2) LDR 指令



LDR 指令简介 : 将 寄存器中的值 保存到 内存中;

-- 语法格式 : ldr r0, 地址;

-- 语法解析 : 将 内存地址中 存放的值 加载入 r0 中;


代码示例 : 


@ldr 指令范例
mov r0, #0xff
@将 r1 值改为 50000000 (OK-6410)
str r0, [r1]
ldr r0, [r1]

7. 以上所有代码示例


以上所有代码示例 : 便于调试学习;


.text

.global _start

_start:


@ldr 指令范例

mov r0, #0xff

@将 r1 值改为 50000000 (OK-6410)

str r0, [r1]

ldr r0, [r1]


@str 指令范例

mov r0, #0xff

@将 r1 值改为 50000000 (OK-6410)

str r0, [r1]


@mrs msr 指令范例

@rs 是 将 s -> r, sr 是 r -> s

mrs r0, cpsr @将 cpsr 中的数据搬移到 r0 中

orr r0, #0b100 程序入口, 用法 '.globol _start', 注意前面加上点;@将 cpsr 中的第三位置为1

msr cprs, r0


@ror 循环右移指令范例

mov r1, #0b11

@结果是 ob1000...0001

mov r1, r1, ror#1


@lsl 左移指令范例

mov r1, #0b1

@将 r1 中的值, 左移 2 位, 放入 r1 寄存器中

mov r1, r1, lsl#2


@bl 带连接的分支指令范例

mov r1, #2

cmp r1, #1

@此时跳转到 func1, func1 执行完程序无法返回, 如果 使用 bl 跳转, 程序会返回

@b func1

@此时使用 bl 跳转到 func1 执行, func1 执行完毕后会返回执行下面的语句

bl func1


mov r1, #2

cmp r1, #3


func1:

mov r1, #2

cmp r1, #2


mov r1, #4

cmp r1, #6


@b 分支指令范例

mov r1, #6

mov r2, #5

cmp r1, r2 @比较 r1 和 r2 中的值

@b 后可以跟一个条件, {条件} 在 {} 中就是可加可不加, 如果没有条件就是无条件100%执行

@gt 是大于条件指令, 如果条件满足会跳转到 branch1, 如果不满足就执行下面的指令

bgt branch1

add r3, r1, r2

b end @这里为了不执行 branch1 操作, 直接跳转到 end 执行


branch1:

sub r3, r1, r2


end:

nop


@cmp 指令范例

[1] [2] [3]
关键字:ARM  汇编  伪指令  协处理器  访问指令 引用地址:【嵌入式开发】 ARM 汇编 (指令分类 | 伪指令 | 协处理器访问指令)

上一篇:基于WINCE6.0+S3C2443的camera驱动
下一篇:【嵌入式开发】ARM 芯片简介 (ARM芯片类型 | ARM处理器工作模式 | ARM 寄存器 | ARM 寻址)

推荐阅读最新更新时间:2024-11-10 19:48

ARM字节对齐问题详解
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有
[单片机]
ARM的异常中断和处理过程
0. ARM异常中断的种类 ARM支持7种异常中断,其中包括复位、未定义指令异常、软中断异常、预取指令中止、数据中止、IRQ、FIQ。 0.1 复位(RESET)(优先级=1) 当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行。复位异常中断通常用在下面几种情况:系统加电时;系统复位时;跳转到复位中断向量处执行成为软复位。 0.2 未定义指令(优先级=6) 当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断,可以通过改异常中断机制仿真浮点向量运算。 0.3 软中断(优先级=6) 这是一个由用户定义的中断指令。用于用户模式下的程序调用特权操作指令。在实
[单片机]
<font color='red'>ARM</font>的异常中断和处理过程
PIC中断汇编例程
PIC中断汇编例程 list p=16f876 #include p16f876.inc ;-------------------------- ;定时计数单元 HW_TIME EQU 0X40 ;----------------------------- ;定时常数 HW_TIMECT0 EQU 0XDF;TMR0定时器时间常数,载波信号频率37.88KHz(13.2us) HW_TIMECT1 EQU 0X64;发送信号位间隔,*(1.32ms) HW_TIMECT3 EQU 0X31; ;-------------------------------------
[单片机]
Arm芯片为何对苹果Mac如此重要
最近关于苹果Mac要转用ARM处理器的消息不胫而走。许多人都希望Apple在其Mac系列产品中迁移到自己的处理器。随着对ARM过渡的清晰认识开始出现,人们可能仍然想知道这意味着什么。苹果从英特尔转向ARM是什么意思?至关重要的是,是什么使这种过渡对Mac的未来如此重要? 总体而言,苹果从Mac上的Intel处理器转移到其他方面,与ARM无关,而更多地与Apple对其计算命运的控制力更大有关。 什么是ARM?它与苹果有什么关系? ARM Holdings是一家英国公司,负责设计和创建自己的CPU和其他芯片组。尽管ARM芯片为各种设备(例如Acorn Archimedes)供电的悠久历史,但如今,该公司及其大多数
[嵌入式]
<font color='red'>Arm</font>芯片为何对苹果Mac如此重要
ARM系列 STM32F103RCT6 开发
简单介绍STM32F1XX系列可以有RTOS ,实时操作系统,也可以直接当单片机用. 功能有adc,dac,bkp,can,cec,crc,dbgmcu,dma,exti,flash,fsmc,gpio,i2c,iwdg,pwr,rcc,rtc,sdio,spi,tim,usart,wwdg,misc 具体芯片的每个接口是什么功能,不同的板子差别不大,毕竟是要符合芯片规范的。 开发环境基本都是WINDOWS(unix-like gcc) , 开发工具有 MDK-ARM(keil), EWARM(IAR),HiTOP, GCC(RIDE),TrueSTUDIO.. 开发IDE中集成了startup文件,gcc也集成了的启动文件
[单片机]
【32位MCU】9G-CM0 新唐CM0+MDK-ARM入门开发过程简介
9G-CM0 新唐CM0+MDK-ARM入门开发过程简介 一,准备MDK-ARM + 新唐CM0软件包 1,在http://www.mcu123.com/news/Soft/embsof/arm/201006/529.html 下载RealView MDK-ARM 4.12 (MDK-ARM V4.12,MDK4.12) mdk412_mcu123.rar 在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=3&SoftID=529上 右击 下载地址: 后的 下载 选择 目标另存为 下载文件到本地硬盘。 (自己查找破解文件 keygen.exe ) http
[单片机]
ARM状态寄存器 CPSR SPSR
CPSR:程序状态寄存器(current program status register) ,cpsr在用户级编程时用于存储条件码。CPSR包含条件码标志,中断禁止位,当前处理器模式以及其他状态和控制信息。   SPSR:程序状态保存寄存器。SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态。 CPSR(当前程序状态寄存器)在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器)。当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断退出时,可以用SPSR来恢
[单片机]
ARM——栈
1 栈:栈是一种具有后进先出的数据组织方式,也就是说后存放的先取出,先存放的后取出。栈底是第一个进栈的数据所处位置,栈顶是最后一个数据进栈所处的位置。 数据组织:有链表、图、树等等(就数据结构那些东东) 2 满/空栈 根据SP指针指向的位置,栈可以分为满栈和空栈。 满栈:当堆栈指针总是指向最后压入堆栈的数据 空栈:当堆栈指针总是指向下一个将要放入数据的空位置   ARM采用满栈 3 升/降栈 根据SP指针移动的方向,栈可以分为升栈和降栈 升栈:随着数据的入栈,SP指针从低地址- 高地址移动 降栈:随着数据的入栈,SP指针从高地址- 低地址移动 ARM采用降栈 注:ARM是满降栈 4 栈帧 上图描
[单片机]
<font color='red'>ARM</font>——栈
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved