ARM指令随记

更新时间:2023-06-18 15:09:31 阅读: 评论:0

ARM指令第二操作数#immed_8r常量问题
在ARM处理器的汇编语言中,对指令语法格式中的<shifter_operand>的常数表达式有这样的规定:“该常数必须对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”
首先从ARM指令系统的语法格式说起。
一条ARM指令语法格式分为如下几个部分:
<opcode>{<cond>}{S} <Rd>,<Rn>{,<shifter_operand>}
其中,<>内的项是必须的,{}内的项是可选的,如<opcode>是指令助记符,是必须的,而{<cond>}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)。
Opcode   指令助记符,如LDR,STR 等
Cond       执行条件,如EQ,NE 等
       S           是否影响CPSR 寄存器的值,书写时影响CPSR,否则不影响
奶粉英文
       Rd          目标寄存器
Rn          第一个操作数的寄存器
shifter_operand      第二个操作数
其指令编码格式如下:
31-28
27-25
24-21
20
19-16
15-12
11-0 (12位)
cond
001
opcode
S
Rn
如何解决心理问题Rd
shifter_operand
     当第2 个操作数的形式为:#immed_8r常数表达式时“该常数必须对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”
假如我是风其意思是这样:#immed_8r在芯片处理时表示一个32位数,但是它是由一个8位数(比如:01011010,即0x5A)通过循环移位偶数位得到(1000 0000 0000 0000 0000 0000 0001 0110,就是0x5A通过循环右移2位(偶数位)的到的)。
而1010 0000 0000 0000 0000 0000 0001 0110,就不符合这样的规定,编译时一定出错。因为你可能通过将1011 0101循环右移位得到它,但是不可能通过循环移位偶数位得到。
1011 0000 0000 0000 0000 0000 0001 0110,也不符合这样的规定,很明显:1 0110 1011 有9位。
为什么要有这样的规定?
要从指令编码格式来解释(这就是我为什么一开始讲的是指令编码格式),仔细看表格中的shifter_operand所占的位数:12位。要用一个12位的编码来表示任意的32位数是绝对不可能的(12位数有2^12种可能,而32位数有2^32种)。
但是又要用12位的编码来表示32位数,怎么办?
只有在表示数的数量上做限制。通过编码来实现用12位的编码来表示32位数。
在12位的shifter_operand中:8位存数据,4位存移位的次数。
8位存数据:解释了“该常数必须对应8位位图”。
4位存移位的次数:解释了为什么只能移偶数位。4位只有16种可能值,而32位数可以循环移位32次(32种可能),那就只好限制:只能移偶数位(两位两位地移,好像一个16位数在移位,16种移位可能)。这样就解决了能表示的情况是实际情况一半的矛盾。
所以对#immed_8r常数表达式的限制是解决指令编码的第二个操作数位数不足以表示32位操作数的无奈之举,但这个可以说是很好的做法。因为如果直接用12位数来表示32位操作数,只能表示0 到(2^12-1)。大于(2^12-1)的数就没办法表示了。而且细细想来“8位存数据,4位存移位的次数”,应该是最好的组合了。
ARM指令第二操作数#immed_8r
大多数ARM通用数据处理指令有一个灵活的第2操作数(flexible cond operand),这里这解释一下其中的一种格式,#immed_8r常量的表达式。常量必须对应于8位位图(pattern)。该位图在32位字中,被循环移位偶数位(0,2,4,...28,30)。合法常量0xff,0xff000,0xf000000f。非法常量:0x101,0xff04
ARM 在32位模式下,一条指令长度为32位,在上述数据处理指令中,操作数2为12位。所以像0x7f02这样的数,要两条指令才能完成。
MOV     R3, #0x7F00    ;E3 A0 3C 7F 该指令自己完成0x7f移位
ORR     R1, R3, #2
所以直接是找不到0x7f02的#immed_8r那个看明白了,但是请问图片里的那个8~11位的循环移位数,0000是不移位;0001是移动2位;0010是移动4位;0011是移动6位这样子吗?那么 0x7F00是7F左移8位指令中变成4 7F请问为什么给出的是C 7F呢?
关于循环移位,其实arm中只有循环右移(ROR)。0x7f到0x7f00是通过循环右移24次才实现的,这里每次移动2位所以是12次(0xc)
溢出位(V)置位有四种情况:
两个整数相加结果为负数时
两个负数相加结果为正数时
一个正数减一个负数结果为负数时
一个负数减一个正数结果为正数时
1、寄存器使用规则
子程序间通过寄存器 r0 ~ r3 来传递参数,这时可以使用它们的别名 a1 ~ a4 。被调用的子程序返回前无需恢复 r0 ~ r3 的内容。
在子程序中,使用 r4 ~ r11 来保存局部变量,这时可以使用它们的别名 v1 ~ v8 。如果在子程序中使用了它们的某些寄存器,子程序进入时要保存这些寄存器的值,在返回前恢复它们;对于子程序中没有使用到的寄存器,则不必进行这些操作。在THUMB程序中,通常只能使用寄存器 r4 ~ r7 来保存局部变量。
寄存器 r12 用作子程序间scratch寄存器,别名为ip。
寄存器 r13 用作数据栈指针,别名为 sp 。在子程序中寄存器 r13 不能用作其他用途。它的值在进入、退出子程序时必须相等。
寄存器 r14 称为连接寄存器,别名为 lr 。它用于保存子程序的返回地址。如果在子程序中保存了返回地址(比如将 lr 值保存到数据栈中), r14 可以用作其他用途。
寄存器 r15 是程序计数器,别名为 pc 。它不能用作其他用途。
寄存器
别名
使用规则
r15
pc
程序计数器
r14
lr
连接寄存器
卜字怎么读r13
sp
数据栈指针林清玄的作品
r12
ip
子程序内部调用的scratch寄存器
峨眉山海拔r11
fp(v8)
ARM状态局部变量寄存器8
r10
休字组词
s1(v7)
ARM状态局部变量寄存器7、在支持数据栈检查的ATPCS中为数据栈限制指针
r9
sb(v6)
ARM状态局部变量寄存器6、在支持RWPI的ATPCS中为静态基址寄存器
r8
v5
ARM状态局部变量寄存器5
r7
wr(v4)
ARM状态局部变量寄存器4、THUMB状态工作寄存器
r6
v3
ARM状态局部变量寄存器3
r5
v2
ARM状态局部变量寄存器2
r4
v1
ARM状态局部变量寄存器1
r3
a4
参数/结果/scratch寄存器4
r2
a3
参数/结果/scratch寄存器3
r1
a2
参数/结果/scratch寄存器2
r0
a1
参数/结果/scratch寄存器1
2、数据栈使用规则
数据栈有两个增长方向:向内存地址减小的方向增长时,称为 DESCENDING栈 ;向内存地址增加的方向增长时,称为 ASCENDING栈 。
所谓数据栈的增长就是移动栈指针。当栈指针指向栈顶元素(最后一个入栈的数据)时,称为 FULL栈 ;当栈指针指向栈顶元素(最后一个入栈的数据)相邻的一个空的数据单元时,称为 EMPTY栈 。
则数据栈可以分为4种:
FD:Full  Descending        满递减
ED:Empty  Descending    空递减
FA :Full  Ascending         满递增
EA:Empty  Ascending      空递增
ATPCS规定数据栈为FD类型,并且对数据栈的操作是8字节对齐的。使用 stmdb / ldmia 批量内存访问指令来操作FD数据栈。
使用stmdb命令往数据栈中保存内容时,先递减sp指针,再保存数据,使用ldmia命令从数据栈中恢复数据时,先获得数据,再递增sp指针,sp指针总是指向栈顶元素,这刚好是FD栈的定义。
3、参数传递规则
一般地,当参数个数不超过 4 个时,使用 r0 ~ r3 这4个寄存器来传递参数;如果参数个数超过 4 个,剩余的参数通过数据栈来传递。
对于一般的返回结果,通常使用 r0 ~ r3 来传递。
例:
假设CopyCode2SDRAM函数是用C语言实现的,它的数据原型如下:
int    CopyCode2SDRAM( unsigned  char  *buf,  unsigned  long  start_addr,  int  size )
在汇编代码中,使用下面的代码调用它,并判断返回值:
ldr    r0,  =0x30000000                 @1. 目标地址 = 0x30000000,这是SDRAM的起始地址
mov    r1,  #0                                 @2. 源地址 = 0
mov    r2,  #16*1024                     @3. 复制长度 = 16K
bl    CopyCode2SDRAM               @调用C函数CopyCode2SDRAM
cmp    a0,  #0                                 @判断函数返回值
状态切换和BX指令
AREA   ADDREG,CODE,READONLY
  ENTRY
MAIN
      ADR r0,ThunbProg + 1 
    BX  r0
      CODE16
ThunbProg
    mov r2,#2
  mov r3,#3
  add r2,r2,r3
  ADR r0,ARMProg
  BX r0
    CODE32
ARMProg
短信怎么发  mov r4,#4
  mov r5,#5
  add r4,r4,r5
    mov r0,#0x18
    LDR r1,=0x20026
    SWI 0x123456
    END
解释:ADR r0,ThunbProg + 1为什么要加1呢?这是因为BX指令中若目标地址的bit[0]为0,则跳转时自动将CPSR中的标志位T复位,即把目标地址的代码解释为ARM代码,若目标地址的bit[0]为1,则跳转时自动将CPSR中的标志位T置位,即把目标代码解释为Thumb代码。
    SWI,即software interrupt软件中断。该指令产生一个SWI异常。意思就是处理器模式改变为管理模式,CPSR寄存器保存到管理模式下的SPSR寄存器,并且跳转到SWI向量。其ARM指令格式如下:
SWI{cond} immed_24
Cond域:是可选的条件码 (参见 ARM汇编指令条件执行详解).
immed_24域:范围从 0 到 224-1的表达式, (即0-16777215),immed_24为软中断号(服务类型)。

本文发布于:2023-06-18 15:09:31,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/984020.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:指令   数据   寄存器   移位   表示
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图