汇编学习笔记

在学习STM32前,需要了解的汇编思想

初始化

                AREA    STACK, NOINIT, READWRITE
__initial_sp
                AREA    RESET, DATA, READONLY
__Vectors       DCD     __initial_sp 
                DCD     main              
                AREA    |.text|, CODE, READONLY
                ENTRY						
main			
				
				
loop
                B loop                  
                END

解释:

1. AREA STACK, NOINIT,READWRITE: 这一行指定了一个名为STACK的内存区域,它用于存储堆栈。NOINIT表示这个内存区域在程序启动时不需要初始化,READWRITE表示这个内存区域可以被读取和写入。

2. __initial_sp: 这一行定义了一个名为__initial_sp的符号,它表示堆栈指针的初始值。在这里,它被定义为堆栈的起始地址。通常,这个符号会在链接脚本中进一步定义为实际的堆栈内存区域的起始地址。

3. AREA RESET, DATA,READONLY: 这一行指定了一个名为RESET的内存区域,用于存储重置向量表。DATA表示这个区域包含数据,READONLY表示这个区域只能被读取。

4. __Vectors DCD __initial_sp: 这一行定义了一个重置向量表,用于指示程序启动时应该执行的操作。DCD表示存储一个双字(32位)的数据。在这里,第一个双字存储的是堆栈指针的初始值,即__initial_sp。

5. DCD main: 这一行将程序的入口地址(main函数)添加到重置向量表中。这意味着程序在启动时将跳转到main函数开始执行。

6. AREA |.text|, CODE,READONLY: 这一行指定了一个名为.text的内存区域,用于存储代码。CODE表示这个区域包含代码,READONLY表示这个区域只能被读取。

7. ENTRY main: 这一行指定了程序的入口点为main函数。这意味着程序将从main函数开始执行。

8. loop B loop: 这一行是一个无限循环,它会不断地跳转到loop标签所在的位置,导致程序永远循环执行这条指令。

9. END: 这一行表示程序的结束。

数据搬运指令MOVS

<font style="color:rgb(44, 44, 54);">MOVS</font> 指令用于在寄存器之间移动数据或从立即数(一个常数值)到寄存器。它的基本格式如下:

<font style="color:#ee9900;">MOVS R0</font><font style="color:#999999;">,</font><font style="color:#000000;">#</font><font style="color:#990055;">2</font>

<font style="color:#ee9900;">MOVS R1</font><font style="color:#999999;">,</font><font style="color:#ee9900;">R0</font>

内存操作

读写

LDR:指令主要用于从内存中加载数据到寄存器,或者可以用来处理地址。

LDR R2,=0X12345678 将数据写入寄存器

LDR R2,[R1] 将R2地址中的内容放入R1,相当于读

MOVS与LDR关键区别

  • 用途<font style="color:rgb(44, 44, 54);">MOV</font> 主要用于寄存器之间的数据移动或加载立即数,而 <font style="color:rgb(44, 44, 54);">LDR</font> 用于从内存中加载数据或处理地址。
  • 操作数<font style="color:rgb(44, 44, 54);">MOV</font> 可以使用寄存器或立即数作为源操作数,而 <font style="color:rgb(44, 44, 54);">LDR</font> 需要一个内存地址或地址表达式作为源。
  • 性能影响:由于 <font style="color:rgb(44, 44, 54);">LDR</font> 涉及到内存访问,它通常比 <font style="color:rgb(44, 44, 54);">MOV</font> 更慢,因为后者只涉及CPU内部的寄存器操作。

STR R0,[R1] 将R0的值写入到R1指向的地址

CPU栈机制

概念

栈是一种具有特殊的访问方式的存储空间,他的特殊性就在于最后一个进入这个空间的数据,是最先出去的

分类

  1. 空栈:指向的地址为空,可以直接存储,存储完成之后需要将栈指针再次指向空的位置。
  2. 满栈: 栈指针指向的地址有数据,在栈中存储数据时,需要先将栈指针,指向一个空的位置,然后在存储数据。
  3. 增栈:栈针向高地址移动
  4. 减栈:栈针向高地址移动

ARM默认采用的是满减栈

栈的基本操作

栈有两种基本的操作:入栈和出栈

  1. 入栈:将一个新的元素放到栈顶
  2. 出栈:从栈顶取出一个元素
  3. 先进后出,后进先出

PUSH和POP

汇编中的两个指令

PUSH:入栈(压栈)

<font style="color:#000000;">PUSH {R0-R3,LR}</font>

POP:出栈(弹栈)

<font style="color:#000000;">POP{R0-R4,PC}</font>

例子

  1. 主程序给R1,R2,R3分别写入数据

然后跳入函数JUMP

2.函数JUMP,函数内修改R1 R3的数值

3.修改结束后返回主函数

4.主函数再使R1和R3原来的数据相加后存入R1

  1. 跳出主程序进入死循环
    AREA    STACK, NOINIT, READWRITE 
__initial_sp                 
    AREA                 RESET, DATA, READONLY 
__Vectors       DCD     __initial_sp                  
    DCD     main                               
    AREA    |.text|, CODE, READONLY                 
    ENTRY 

main
  ADD SP,SP,#0X100;向上移动栈针,因为是满减栈
  LDR R1,=0X12345678
	LDR R2,=0X22222222
	LDR R3,=0X33333333;赋值
  BL JUMP;跳转到JUMP函数并且保存返回地址
  ADD R1,R1,R3
  B loop ;跳转到loop函数
  
JUMP
  PUSH {{R0-R3,LR};保护现场,将原来的数据压栈,并在最后保存了函数的返回地址
  ;进行操作
  LDR R1,=0X00000001;
	LDR R3,=0X10000000;	
  POP{R0-R3,PC}	;恢复现场,将数据出栈,恢复了R0~R3的值,并将保存的地址赋给PC指针,程序将跳转值函数调用位置运行


loop                 
    B loop    

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值