嵌入式养成计划-51----ARM--ARM汇编指令--内存读写指令--程序状态寄存器传输指令--软中断指令--混合编程

news2024/11/27 7:41:32

一百二十七、内存读写指令

  • 通过内存读写指令可以实现向内存中写入指定数据或者读取指定内存地址的数据

127.1 单寄存器内存读写指令

  • 将一个寄存器中的数值写入到内存,或者从内存中读取数据放在某一个指定寄存器中

127.1.1 指令码和功能

1. 向内存中写:
str{条件码} 目标寄存器,[目标地址]	:	将目标寄存器的4字节数值写入到目标地址为首地址的空间中
strh{条件码} 目标寄存器,[目标地址]	:	将目标寄存器的2字节数值写入到目标地址为首地址的空间中
strb{条件码} 目标寄存器,[目标地址]	:	将目标寄存器的1字节数值写入到目标地址为首地址的空间中

2. 从内存中读:
ldr{条件码} 目标寄存器,[目标地址]	:	从目标地址为首地址的空间中读取4字节数据存放在目标寄存器中
ldrh{条件码} 目标寄存器,[目标地址]	:	从目标地址为首地址的空间中读取2字节数据存放在目标寄存器中
ldrb{条件码} 目标寄存器,[目标地址]	:	从目标地址为首地址的空间中读取1字节数据存放在目标寄存器中

127.1.2 示例

.text  
.global start 
_start:
	mov r0,#0XFFFFFFFE
	mov r1,#0X40000000  @R1保存内存地址
	@将r0的值写入到r1对应的地址空间
	str r0,[r1]
	@从r1对应的地址空间中读取数据保存在r2中
	ldr r2,[r1]
wh: 
	b wh  
.end 

在这里插入图片描述

127.1.3 单寄存器内存索引方式

  • 前索引方式
    str{条件码} 目标寄存器,[目标地址,#立即数]
    	//将目标寄存器的数据保存在目标地址+8为起始地址的内存中
    ldr{条件码} 目标寄存器,[目标地址,#立即数]
    	//从目标地址+8为起始地址的内存中读取数据保存在目标寄存器
    
    在这里插入图片描述
  • 后索引方式
    str{条件码} 目标寄存器,[目标地址],#立即数
    	//将目标寄存器的数据保存在目标地址为起始地址的内存中,接着目标地址自加立即数大小
    ldr{条件码} 目标寄存器,[目标地址],#立即数
    	//从目标地址为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小
    
    在这里插入图片描述
  • 自动索引方式
    str{条件码} 目标寄存器,[目标地址,#立即数]!
    	//将目标寄存器的数据保存在目标地址+立即数为起始地址的内存中,接着目标地址自加立即数大小
    ldr{条件码} 目标寄存器,[目标地址,#立即数]!
    	//从目标地址+立即数大小为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小
    
    在这里插入图片描述

127.2 批量寄存器的内存读写方式

  • 将多个寄存器的数据存放在内存中以及从内存中取出数据保存在多个寄存器中

127.2.1 指令码以及格式

向内存写:
	stm 目标地址,{目标寄存器列表}
		将列表中各个寄存器的数值保存在目标地址对应的地址空间中 
从内存读:
	ldm 目标地址,{目标寄存器列表}
		从目标地址对应的地址空间中拿数据保存到寄存器列表中各个寄存器中

注意:
1. 寄存器列表中每一个寄存器之间用','分隔,
	如果寄存器列表中寄存器的编号连续,那么可以用-表示一定范围内的寄存器,比如 {r1-r5}
2. 无论寄存器列表中的寄存器表现形式如何,在存取数据时始终是小编号寄存器对应低地址

127.2.2 示例

.text  
.global start 
_start:
	mov r0,#0X40000000
	mov r1,#1
	mov r2,#2
	mov r3,#3
	mov r4,#4
	mov r5,#5
	@向内存中写
	@stm r0,{r2,r1,r4,r3,r5}
	stm r0,{r1-r5}
	@从内存中读取数据
	ldm r0,{r6-r10}
wh: 
	b wh  
.end 

在这里插入图片描述

127.2.3 批量寄存器的地址增长方式

  • 每次向寄存器保存的地址对应的地址空间中写入一个数据,这个寄存器保存的地址会发生相应的增长变化,这就是批量寄存器的地址增长方式
    .text  
    .global start 
    _start:
    	mov r0,#0X40000000
    	mov r1,#1
    	mov r2,#2
    	mov r3,#3
    	mov r4,#4
    	mov r5,#5
    	@向内存中写
    	stm r0!,{r1-r5}
    wh: 
    	b wh  
    .end 
    
    在这里插入图片描述
  • 内存读写命令后加ia后缀
    先向 R0 寄存器存放的地址指向的内存空间中保存一个数据,然后 R0 寄存器指向的地址往高地址方向增长
  • 内存读写命令后加ib后缀
    先 R0 寄存器指向的地址往高地址方向增长,然后向 R0 寄存器存放的地址指向的内存空间中保存一个数据
  • 内存读写命令后加da后缀
    先向 R0 寄存器存放的地址指向的内存空间中保存一个数据,然后 R0 寄存器指向的地址往低地址方向增长
  • 内存读写命令后加db后缀
    先 R0 寄存器指向的地址往低地址方向增长,然后向 R0 寄存器存放的地址指向的内存空间中保存一个数据

127.3 栈内存的读写

  • 栈指针寄存器:SP/R13 保存栈顶的地址
  • 栈:本质上就是一段内存。在内存中选取一段内存作为栈内存,可以用于保存临时数据。

127.3.1 栈内存的读写

增栈	:	每次压栈结束,SP保存的栈顶地址往高地址方向增栈
减栈	:	每次压栈结束,SP保存的栈顶地址往低地址方向增栈

空栈	:	压栈结束后,SP保存的栈顶空间中没有有效数据
满栈	:	压栈结束后,SP保存的栈顶空间中有有效数据

其本质就是先改变指向还是先存放数据

空增栈(EA)/空减栈(ED)/满增栈(FA)/满减栈(FD)
E	:	empty 空			F	:	full 满
A	:	addition 增加		D	:	delete 减少

当前ARM处理器使用的是哪种栈?满减栈

127.3.2 满减栈压栈出栈操作

  1. push {寄存器列表}@压栈
    pop {寄存器列表}@出栈
  2. .text  
    .global start 
    _start:
    	@初始化栈
    	ldr SP,=0X40000020
    	mov r1,#1
    	mov r2,#2
    	mov r3,#3
    	mov r4,#4
    	mov r5,#5
    	@压栈
    	stmdb sp!,{r1-r5}
    	@出栈
    	ldmia sp!,{r6-r10}
    wh: 
    	b wh  
    .end 
    
  3. .text  
    .global start 
    _start:
    	@初始化栈
    	ldr SP,=0X40000020
    	mov r1,#1
    	mov r2,#2
    	mov r3,#3
    	mov r4,#4
    	mov r5,#5
    	@压栈
    	stmfd sp!,{r1-r5}
    	@出栈
    	ldmfd sp!,{r6-r10}
    wh: 
    	b wh
    .end 
    

127.3.3 栈的应用实例—叶子函数调用过程

  • 当我们在主函数中调用一个函数,被调用的这个函数中没有别的函数调用,那么 这个函数就叫做叶子函数

如:

.text  
.global _start 
_start:
	@初始化栈
	ldr SP,=0X40000020
	b main
main:
	mov r1,#3
	mov r2,#4
	bl fun1
	add r3,r1,r2
	b main
fun1:
	@压栈保护现场
	stmfd sp!,{r1,r2}
	mov r1,#7
	mov r2,#9
	sub r4,r2,r1
	@出栈恢复现场
	ldmfd sp!,{r1,r2}
	mov pc,lr   @程序返回
.end 

127.3.4 栈的应用实例—非叶子函数调用过程

  • 当我们在主函数中调用一个函数,被调用的这个函数中存在别的函数调用,那么 这个函数就叫做非叶子函数
.text  
.global _start 
_start:
	@初始化栈
	ldr SP,=0X40000020
	b main
main:
	mov r1,#3
	mov r2,#4
	bl fun1
	add r3,r1,r2
	b main
fun1:
	@压栈保护现场
	stmfd sp!,{r1,r2,lr}
	mov r1,#7
	mov r2,#9
	bl fun2
	sub r4,r2,r1
	@出栈恢复现场
	ldmfd sp!,{r1,r2,lr}
	mov pc,lr   @程序返回
fun2:
	stmfd sp!,{r1,r2}
	mov r1,#4
	mov r2,#8
	mul r4,r2,r1
	@出栈恢复现场
	ldmfd sp!,{r1,r2}
	mov pc,lr   @程序返回
.end

一百二十八、程序状态寄存器传输指令

  • 指令的作用实现CPSR寄存器数值的读取以及数值的修改

128.1 指令码以及格式

格式:
msr CPSR,第一操作数
	将第一操作数的数值写入到CPSR寄存器中
mrs 目标寄存器,CPSR
	读取CPSR数值保存到目标寄存器中

128.2 实例

.text  
.global _start 
_start:
	mrs r1,CPSR  @读取CPSR数值
	@切换到USR模式,取消FIQ和IRQ禁止
	msr CPSR,#0x10
.end 

注意:
user模式是ARM处理器工作模式中唯一的非特权模式,
这种模式下无法通过手动修改CPSR数值切换到特权模式,
只有发生对应的异常后才可以切换到异常模式

一百二十九、软中断指令

129.1 软中断概念

  • 软中断是从软件层次上模拟的硬件中断,原理和硬件中断一样。
  • 软中断触发之后CPU进行异常模式的切换(SVC),紧接着执行软中断对应的异常处理程序。

129.2 软中断指令码以及使用

  • swi 中断号
  • 注意:中断号是一个由24位二进制数组成的一个整数,用于区分不同的中断

129.3 异常处理过程分析

129.3.1 异常模式和异常源的对应关系

  • 5种异常模式对应7种异常源

    异常模式异常源解释
    FIQFIQ类型异常源一些硬件发生了FIQ异常事件进入FIQ模型
    IRQIRQ类型异常源一些硬件发生了IRQ异常事件进入IRQ模型
    SVC复位信号按键复位/上电复位时产生
    swi软中断指令执行swi指令
    undef未定义异常源译码器在翻译指令时,遇到无法翻译的指令,指令未定义
    abortdata abort取数据发生异常时
    prefetch abort取指令发生异常时

129.3.2 异常的处理过程分析(面试重点)

  • 异常的处理过程
    当一个异常源产生之后CPU会进行一些工作用于程序的跳转以及异常模式的切换,这个过程分为四大步三小步
    1. 保存发生异常之前的CPSR的值到对应异常模式下的SPSR寄存器中
    2. 修改CPSR的数值
        2.1	根据实际情况设置FIQ和IRQ中断禁止  CPSR[7:6]
        2.2 修改处理器工作状态为ARM状态  CPSR[5]
        2.3 修改处理器的工作模式为对应的异常模式 CPSR[4:0]
    3. 保存主程序的返回地址到对应模式下的LR寄存器中
    4. PC的值到对应异常模式下的异常向量表中
    
  • 处理完异常之后现场的恢复过程
    1. 恢复CPSR寄存器的值为未发生异常之前的状态
    2. 修改PC的值为未发生异常之前的下一条指令地址   PC=LR
    
    在这里插入图片描述

129.3.3 异常向量表

  1. 异常向量表是内存空间中的一段内存。
    这段内存占据了32字节,被平分为8等份,一份是4字节。
    每一份内存对应一种异常源,有一份保留,在异常向量表内存里存放的是当前异常源对应的异常处理程序的跳转指令。
    当发生异常之后,CPU会修改PC的值为对应异常源在异常向量中的位置,执行这个位置中的跳转指令,去处理异常处理程序。
  2. 每一种异常源在异常向量表中的位置是固定,不能随便修改。
  3. 只要设置了异常向量表的基地址,就可以根据不同异常在一场向量表中的位置找到对应异常的跳转指令。
    在这里插入图片描述

129.4 软中断异常处理实例

.text  
.global _start 
_start:
	@初始化异常向量表
	b main
	b .
	b do_swi
	b .
	b .
	b .
	b .
	b .
main:
	@初始化栈
	mov sp,#0X40000020
	@切换到USER模式
	MSR CPSR,#0X10
	MOV R1,#1
	MOV R2,#2
	@触发软中断
	SWI 1
	add r3,r1,r2
	b main
	
@异常处理
do_swi:	
	@保护现场
	stmfd sp!,{r1,r2,lr}
	mov r1,#3
	mov r2,#4
	mul r4,r1,r2
	@恢复现场
	ldmfd sp!,{r1,r2,pc}^  @  ^的作用是修改PC的值的同时将SPSR的值赋值给CPSR
.end

一百三十、混合编程

130.1 混合编程的意义

  • 所谓的混合编程就是c语言资源和汇编资源的相互调用
    • 一般工程会有汇编启动程序,启动程序完成堆栈的相关初始化,完毕之后才跳转到c语言的main函数
    • c语言中几乎不可以直接操作寄存器,但是有些特定场景下需要c中操作寄存器,这时候就需要c语言中嵌套汇编的语法

130.2 混合编程概述

  • 要想实现C和汇编的混合编程必须遵循ATPCS规范。

  • ATPCS : ARM-Thumb Procedure Call Standard

    int add(int i,int j)
    {
        return i+j;
    }
    
  • 将汇编的标签当作C语言的函数使用

  • 将C语言的函数当作汇编的标签使用

  • 函数参数的传递采用R0-R3进行传递,如果参数的个数大于4个通过压栈的方式进行传递

  • 函数的返回值通过R0返回,如果函数的返回值大于4个字节通过r0-r1返回。

  • ATPCS规范中规定ARM采用满减栈。

130.3 汇编调用C语言的函数

  • 将C语言的函数当作汇编的标签使用

示例:

  • 汇编文件
    .text    
    .global _start  
    _start: 
    	@ 1. 初始化栈指针,C代码运行必须有栈
    	ldr sp, =0x40000820
    	
    	@ 2. 汇编调用c函数 
    	@ 2.1 给C的函数传递实参值
    	mov r0, #3   @ a = 3
    	mov r1, #4   @ b = 4
    	mov r2, #5   @ c = 5
    	mov r3, #6   @ d = 6
    	
    	@ 2.2 汇编调用c的函数
    	bl add_func
    	
    	@ 2.3 函数的返回通过r0返回,查看r0寄存器中的值
    loop:   
    	b loop  
    .end
    
  • c文件
    // c代码的函数是一个全局的函数
    int add_func(int a, int b, int c, int d) 
    {
    	return (a+b+c+d);
    }
    

130.4 c语言调用汇编标签

  • 将汇编的标签当作c语言的函数

示例:

  • 起始汇编文件
    .text    
    .globl _start  
    _start: 
    	@ 1. 初始化栈指针,C代码运行必须有栈
    	ldr sp, =0x40000820
    	
    	@ 2. 汇编调用c,跳转到main函数
    	b main
    .end
    
  • c文件
    // 使用extern对函数进行声明
    extern int add_func(int a, int b, int c, int d);
    
    int sum = 0;
    int main()
    {
    	// 在c代码中调用汇编代码
    	sum = add_func(1,2,3,4);
    	while(1);
    	return 0;
    }
    
  • 汇编文件
    .text 
    .global add_func  	@ 将add_func函数声明为全局
    
    add_func:
    	add r0, r0, r1
    	add r0, r0, r2
    	add r0, r0, r3
    	mov pc, lr
    .end
    

130.5 c语言内联汇编

  • 在某一些特定的场景下需要在c语言中直接使用汇编的语法,此时需要内联汇编。内联汇编的实现需要通过asm关键字进行修饰

130.5.1 格式

asm volatile(
	"汇编指令模板\n\t"     //"\n\t"表示一条指令的结束
	.....
	:输出列表  //指令结果的输出值
	:输入列表  //指令的数据输入
	:破坏列表  //破坏列表指定我们当前可用的寄存器
);

130.5.2 实例

  • 汇编启动文件
    .text    
    .globl _start  
    _start: 
    	@ 1. 初始化栈指针,C代码运行必须有栈
    	ldr sp, =0x40000820
    	
    	@ 2. 汇编调用c,跳转到main函数
    	b main
    .end
    
  • c语言文件
    // 内联汇编 
    int add_func2(int a, int b, int c, int d)
    {
    	int sum = 0;
    	// 使用汇编实现求和
    	asm volatile(  "add r0, r0, r1\n\t"  "add r0, r0, r2\n\t"  "add r0, r0, r3\n\t"  :"=r"(sum)  :"r"(a),"r"(b),"r"(c),"r"(d)  :"memory" );
    	return sum;
    }
    	//"=r"(sum)表示输出从寄存器中放到变量sum中
    	// "r"(a) 指定输入从变量a中获取放到通用寄存器
    	//"memory"声明使用内存
    
    // 使用extern对函数进行声明
    extern int add_func(int a, int b, int c, int d);
    
    int sum = 0;
    
    int main()
    {
    	// 调用内联汇编的函数 
    	sum = add_func2(5,6,7,8);
    	
    	// 在c代码中调用汇编代码
    	sum = add_func(1,2,3,4);
    	while(1);
    	return 0;
    }
    
  • 汇编文件
    .text 
    .global add_func  @ 将add_func函数声明为全局
    
    add_func:
    	add r0, r0, r1
    	add r0, r0, r2
    	add r0, r0, r3
    	mov pc, lr
    .end
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1188426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

求极限问题:x趋于0时的等价替换及其适用条件、洛必达法

x趋于0时的等价替换及其适用条件 等价无穷小的定义: 若 lim ⁡ β α 1 \lim\dfrac{\beta}{\alpha}1 limαβ​1,则 β \beta β 与 α \alpha α 是等价无穷下的,记作 α ∼ β \alpha \sim \beta α∼β. 即当两个函数相比取极限&…

数据结构与算法(Java版) | 万字详解算法的时间复杂度

下面我们用一个问题来引出算法的时间复杂度这一概念。 该问题是,怎么去衡量一个程序(或者算法)的执行时间呢?就拿我们刚刚讲的排序算法来说,排序算法这么多,你又如何知晓哪一个排序算法执行的时间谁长谁短…

【ElasticSearch系列-07】ES的开发场景和索引分片的设置及优化

ElasticSearch系列整体栏目 内容链接地址【一】ElasticSearch下载和安装https://zhenghuisheng.blog.csdn.net/article/details/129260827【二】ElasticSearch概念和基本操作https://blog.csdn.net/zhenghuishengq/article/details/134121631【三】ElasticSearch的高级查询Quer…

如何制作产品图册?教你一招,轻松制作

制作产品图册是许多企业都会做的一项工作,它可以帮助企业更好地展示自己的产品,提高品牌形象和销售业绩。但是,如何制作一本高质量的产品图册呢?今天,我就来分享一些实用的技巧和方法,帮助你轻松制作一本精…

java实现前后端分离文件下载

前言,这里用的是springbootvue前后端分离 首先我们把需要下载的文件放入到resource目录下面 RestController RequestMapping("/excelDown") Slf4j public class InvestExcelDownController {//下载模板PostMapping("/download")public void dow…

SOME/IP 协议介绍(三)参数和数据结构的序列化

参数和数据结构的序列化 序列化是基于接口规范定义的参数列表。为了允许服务接口的迁移,反序列化,代码应忽略附加在先前已知的参数列表末尾的参数;也就是说,忽略在用于生成或参数化反序列化代码的接口规范中未定义的参数。 接口…

java动态设置注解值

描述:在运行时根据需求更改注解中的值 一、步骤 1.定义类 public class CadreListQueryDTO extends CadreBaseQueryDTO {/*** 出国事由*/QueryField(field "A21.a2114",type QueryField.LIKE)private String a2114; }2.定义方法进行动态设置 /*** 动…

Maven 从入门到精通

目录 一. 前言 二. Maven 下载与安装 2.1. 下载 2.2. 安装 三. Maven 核心概念 3.1. POM 3.2. 约定的目录结构 3.3. 坐标 3.4. 依赖管理 3.4.1. 直接依赖和间接依赖 3.4.2. 依赖的排除 3.4.3. 统一的版本管理 3.4.4. 依赖范围 3.5. 仓库 3.6. 生命周期/插件/目标…

去中心化数据云项目Oort主网即将上线

备受期待的去中心化数据云项目Oort,今日已通过官方X账号官宣,将于纽约时间11月27日正式上线主网Olympus Protocol。届时,用户也能够通过Oort的Ale Wallet钱包和开发者API使用主网,并可通过OORT浏览器查询交易和合约,开…

OpenAI开源全新解码器,极大提升Stable Diffusion性能

在11月7日OpenAI的首届开发者大会上,除了推出一系列重磅产品之外,还开源了两款产品,全新解码器Consistency Decoder(一致性解码器)和最新语音识别模型Whisper v3。 据悉,Consistency Decoder可以替代Stabl…

如何实现Debian工控电脑USB接口安全管控

Debian 作为工控电脑操作系统具有稳定性、安全性、自定义性和丰富的软件包等优势,适用于要求高度可靠性和安全性的工控应用。 Debian 作为工控电脑操作系统在工业控制领域有很大优势,包括: 稳定性:Debian 的发布版以其稳定性而闻…

等保评测是什么意思

等保评测是一种信息安全评估标准,是国家信息安全管理机构为确保信息安全而对信息系统的安全性能进行定期评估的行为。它主要用于评估网络安全的实现情况,包括组织和技术。 等保评测具有系统性和综合性,能够及时发现网络安全风险,…

云闪付app拉新 地推和网推百搭项目 升级涨价啦 附一手渠道

云闪付为银联的支付产品,在地推网推拉新项目市场里也是比较稳定的项目 可以通过”聚量推客“ 渠道申请推广 今天平台拿到了更好的政策价格 价格再次上涨,地推和网推的小伙伴们可以申请推广哦,百搭项目

基于范数求解缩放因子方法的MIMO系统预编码技术matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. MIMO系统模型 4.2. 基于范数求解缩放因子的预编码技术 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心程序 。。。。。。。。。。。。。。。…

使用Docker部署开源分布式任务调度系统DolphinScheduler

🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 使用Docker部署开源分布式任务调度系统DolphinScheduler 文章目录 使用Docker部署开源分布式任务…

计数排序【java实现】

一、计数排序 排序特点: 输入元素大于等于零,当输入的元素是 n 个 0 到 k 之间的整数时,它的运行时间是 O(n k)。计 数排序不是比较排 序,排序的速度快于任何比较排序算法。适合数据范围小的数组。 核心思想: 找出…

Java单元测试及常用语句

1、前言 编写Java单元测试用例,即把一段复杂的代码拆解成一系列简单的单元测试用例,并且无需启动服务,在短时间内测试代码中的处理逻辑。写好Java单元测试用例,其实就是把“复杂问题简单化,建单问题深入化“。在编写的…

Python - 利用 OCR 技术提取视频台词、字幕

目录 一.引言 二.视频处理 1.视频样式 2.视频截取 ◆ 裁切降帧 ◆ 处理效果 3.视频分段 三.OCR 处理 1.视频帧处理 2.文本识别结果 3.后续工作与优化 ◆ 识别去重 ◆ 多线程提效 ◆ 片头片尾优化 四.总结 一.引言 视频经常会配套对应的台词或者字幕&#xff0c…

11.斐波那契数列【兔子生崽】

文章目录 前言一、题目描述 二、解题 前言 本系列为循环结构编程题,点滴成长,一起逆袭。 一、题目描述 二、解题 古典问题(兔子生崽)

k8s存储卷 PV和PVC

目录 emptyDir存储卷 hostPath存储卷 nfs共享存储卷 PVC 和 PV 生命周期 一个PV从创建到销毁的具体流程如下: 静态pvc 动态pvc 3、定义PVC 4、测试访问 搭建 StorageClass NFS,实现 NFS 的动态 PV 创建 1、在stor01节点上安装nfs&#xff0…