ARM汇编基础笔记

       本文记录学习ARM汇编时遇到的问题及其解释,如有错误,乞望指正!

       汇编语句LDR r0, =(0xF << 20)中的“=”是什么意思?
       先说结论:源操作数前有“=”说明本条汇编语句中的汇编指令是伪指令

       LDR:大范围的地址读取伪指令。
       LDR伪指令将一个32位的常数或者一个地址读取到寄存器中。
语法格式:
LDR {cond} register, =[expr | label-expr]
cond:可选的指令执行的条件;
register:目标寄存器;
expr:为32位的常量。编译器将根据expr的取值情况,处理LDR伪指令。
       当expr表示的地址值没有超过MOV或MVN指令中地址的取值范围时,编译器用合适的MOV或者MVN指令替代该LDR伪指令。
       例如:LDR R1, =0XFF0,将0xff0读取到R1中
       汇编后得到MOV R1, 0XFF0
       当expr表示的地址值超过了MOV或MVN指令中地址的取值范围时,编译器将该常数凡在数据缓冲区中,同时用一条基于PC的LDR指令读取该常数。
       例如:LDR R1, =0xFFF,将0xfff读取到R1中。
       汇编后得到:

LDR R1, [PC,OFFSET_TO_LPOOL]
...
LPOOL DCD 0XFFF

label-expr:为基于PC的地址表达式或者是外部表达式。当label-expr为基于PC的地址表达式时,编译器将label-expr表示的数值放在数据缓冲区中,同时用一条基于PC的LDR指令读取该数值。当label-expr为外部表达式,或者非当前段的表达式时,汇编编译器将在目标文件中插入连接重定位伪操作,这样链接器将在连接时生成该地址。
       例如:LDR R1, =ADDR1,将外部地址ADDR1读取到R1中。
       汇编后将得到:

LDR R1, [PC, OFFSET_TO_LPOOL]
...
LPOOL DCD ADDR1

LDR伪指令主要有一下两种用途:
       ①当需要读取到寄存器中的数据超过了MOV及MVN指令可以操作的范围时,可以使用LDR伪指令将改数据读取到寄存器中。
       ②将一个基于PC的地址值或者外部的地址值读取到寄存器中。由于这种地址值是在连接时确定的,所以这种代码不是位置无关的。同时,LDR伪指令处的PC值到数据缓冲区中的目标数据所在的地址的偏移量要小于4KB。
ARM中伪指令不是真正的ARM指令或者Thumb指令,这些伪指令在汇编编译器对源程序进行汇编处理时被替换成对应的ARM或者Thumb指令(序列)。

       ARM NEON 是适用于ARM Cortex-A和Cortex-R52系列处理器的一种128位SIMD(single instruction multiple data, 单指令多数据)扩展结构。

关于满堆栈和空堆栈
       满堆栈(full stack,“F”)是指堆栈指针指向堆栈的最后一个已使用的地址或者满位置(也就是sp指向堆栈最后一个数据项位置)。
       空堆栈(empty stack,“E”)是指sp指向堆栈的第一个没有使用的地址或者空位置(也就是说sp指向堆栈最后一个数据项的下一个位置)。
如下图:
在这里插入图片描述
       指令上加上后缀FA、FD、EA、ED(F-满位置,E-空位置,A-递增,D-递减)来表示sp指针的寻址方式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

       CPSID(关) CPSIE(开) 用于快速的开关中断。

ARM汇编中的^:
       '^'是一个后缀标志,不能在User模式和Sys系统模式下使用该标志.该标志有两个存在目的:
       ①对于LDM操作,同时恢复的寄存器中含有pc(r15)寄存器,那么指令执行的同时cpu自动将spsr拷贝到cpsr中。
       ②数据的送入、送出发生在User用户模式下的寄存器,而非当前模式寄存器。

内嵌汇编的通用形式:

 asm (
   代码
   : 输出操作数列表
   : 输入操作数列表
   : 破坏列表
 );

破坏列表:
        一般就是一个“memory",或者寄存器列表。如果在汇编代码中修改了内存中的值,我们就需要在破坏列表中加上"memory"字段,告诉编译器,我们修改了内存中的值。如果在汇编代码中修改了某些寄存器,那么我们就需要把在代码中所修改过的寄存器列在破坏列表中。
例:

STATIC INLINE INT32 LOS_AtomicAdd(Atomic *v, INT32 addVal)
{
    INT32 val;
    UINT32 status;

    do {
        __asm__ __volatile__("ldrex   %1, [%2]\n"
                             "add   %1, %1, %3\n"
                             "strex   %0, %1, [%2]"
                             : "=&r"(status), "=&r"(val)
                             : "r"(v), "r"(addVal)
                             : "cc");
    } while (__builtin_expect(status != 0, 0));

    return val;
}

       status和val是输出操作数,Atomic *v和INT32 addVal是输入操作数。
       其中%0、%1、%2、%3分别代表status、val、v、addVal。
       “cc”:表示内嵌汇编代码影响状态寄存器相关的标志位;

LDM指令的"!“和”^"

    LDMFD   SP, {R13, R14}^
    LDMFD   SP!, {R0-R3, R12, LR} 

       “^”后缀不允许在用户模式呈系统模式下使用,若在 LDM 指令用寄存器列表中包含有 PC 时使用,那么除了正
常的多寄存器传送外,将 SPSR 拷贝到 CPSR 中,这可用于异常处理返回;使用“^”后缀进行数据传送且寄存器列表不包含 PC 时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。
       后缀“!”表示最后的地址写回到Rn中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值