您的位置:首页 > 其它

ARM汇编基础

2017-04-25 08:50 281 查看

ARM体系平台手册笔记05

并行加减指令

除了正常的数据处理和乘法指令之外,ARMv6还引入了一组并行加减指令
下面介绍6种基本的指令
ADD16
添加两个寄存器的顶部半字形成结果的上半部分。
添加相同两个寄存器的底部半字形成结果的底部半字部分
ADDSUBX
交换第二个操作数寄存器的半字,加上半字,减半字。
为啥这样设计,这里暂时不明白,后续章节有详细介绍
<opcode3>{<cond>} {S} <Rd> <Rn> <shifter_operand>
参照上面描述的指令格式,第二操作数实际上交换的shifter_operand
SUBADDX
交换第二个操作数寄存器的半字,减去顶部半字,并增加底部半字
SUB16
从第二个操作数寄存器的上半部分减去第一个操作数寄存器的上半部分,形成结果的上半部分。
从第一个操作数寄存器的下半部分减去第二个操作数寄存器的下部半字,形成结果的下半部分。
ADD8
将第二个操作数寄存器的每个字节添加到第一个操作数寄存器的相应字节,以形成结果的相应字节
SUB8
将第一个操作数寄存器的相应字节中减去第二个操作数寄存器的每个字节,以形成结果的相应字节。

六种指令中的每一个可用于以下变体,即为这六种指令添加前缀:
有符号指示前缀:
S  符号算术模2^8或2^16.设置CPSR GE位(请参见第A2-13页的GE [3:0]位)。
Q  有符号饱和算术
SH  有符号算术,将结果减半以避免溢出
无符号指示前缀:
U  无符号运算模2^8或2^16.设置CPSR GE位(参见第A2-13页的GE [3:0]位)
UQ  无符号饱和算术
UH  无符号算术,将结果减半以避免溢出
仅仅拿有符号前缀S Q SH举例:(后续章节由对这些指令用法有详细的文档说明)
SADD16 SADDSUBX SUBADDX SSUB16 SADD8 SSUB8
QADD16 QADDSUBX QSUBADDX QSUB16 QADD8 QSUB8
SHADD16 SHADDSUBX SHSUBADDX SHSUB16 SHADD8 SHSUB8
后续章节指令有详细介绍


扩展指令

ARMv6及更高版本提供了几个指令,用于通过符号或零扩展字节到半字或字,以及将字的半字打包数据。
您可以选择将结果添加到另一个寄存器的内容。您可以在扩展之前将操作数寄存器的任意倍数旋转8位

下面介绍6种基本的指令:
XTAB16 将一个寄存器的位[23:16]和位[7:0]扩展为16位,并将相应的半字添加到另一个寄存器中的值。
XTAB 将一个寄存器的位[7:0]扩展为32位,并将其添加到另一个寄存器中的值。
XTAH 将一个寄存器的位[15:0]扩展为32位,并将其添加到另一个寄存器中的值。
XTB16 将位[23:16]和位[7:0]分别扩展为16位
XTB 将扩展位[7:0]至32位
XTH 将位[15:0]扩展为32位

六种指令中的每一个可用于以下变体,即为这六种指令添加前缀:
S 符号扩展,带或不带加法模 数2^16或2^32。
U 零(无符号)扩展名,带或不带加法模 数2^16或2^32
仅拿符号前缀U举例
UTXAB16 UTXAB UXTAH UXTB16 UXTB UXTH
后续章节有详细指令介绍


杂项算术指令

ARMv5及以上版本包括几个其他算术指令。
Count Leading zeros(CLZ)指令。
该指令在遇到第一个1位之前返回其操作数最高有效位的0个数(如果操作数为0,则返回32位)。
大白话,对寄存器直进行移位操作,直到最高位为1时停止移位,并记下移了多少次。

这两个典型的应用是:
1、要确定操作数应该向左移动多少位以使其正常化,以使其最高有效位为1(可用于整数除法程序)
2、要定位最高优先级位在哪一个掩码位(置)上

Unsigned sum of absolute differences(USAD)指令
ARMv6引入了无符号绝对差值(USAD8)指令和无符号绝对差值和累加(USADA8)指令

这些指令执行以下操作:
1.从两个寄存器取相应字节。
2.找出每对字节的无符号值之间的绝对差值。
3.求和四个绝对值。
4.可选地,将绝对差的和累积到第三寄存器中的值

其他杂项指令
PKHBT
(Pack Halfword Bottom Top)将其第一个操作数的底部,最不重要的半字与其移位的第二个操作数的顶部(最重要)半字组合。偏移是从0到31的任意数量的左移。
PKHTB
(Pack Halfword Top Bottom)将其第一个操作数的顶部,最重要的半字与其移位的第二个操作数的底部(最低有效)半字组合。这个变化是一个算术右移,任意数量从1到32
REV
(Byte-Reverse Word)反转32位寄存器中的字节顺序    有意思的指令额^_^
REV16
(Byte-Reverse Packed Halfword)反转32位寄存器的每个16位半字的字节顺序。

REVSH(Byte-Reverse Signed Halfword)
反转32位寄存器的低16位半字的字节顺序,符号将结果扩展为32位。
SEL
根据GE标志的值,从其第一个操作数或其第二个操作数中选择其结果的每个字节。

SSAT(Signed Saturate)
将有符号的值饱和为有符号范围。您可以选择饱和发生的位位置。您可以在饱和发生之前对值进行移位。
USAT(Unsigned Saturate)
将有符号值饱和为无符号范围。您可以选择饱和发生的位位置。您可以在饱和发生之前对值进行移位
USAT16
将两个带符号的16位值饱和为无符号范围。您可以选择饱和发生的位位置
后续章节有详细指令介绍


CPSR访问指令

有两个指令用于将程序状态寄存器的内容移动到通用寄存器或从通用寄存器移出。可以访问CPSR和SPSR
此外,在ARMv6中,有几个指令可以直接写入CPSR中的特定位或位组。
每个状态寄存器传统上分为四个8位字段,可以单独写入:
Bits[31:24] 标志字段
Bits[23:16] 状态字段
Bits[15:8] 扩展字段
Bits[7:0] 控制字段

CPSR value
改变CPSR的值有五个用途:
•将条件代码标志(以及存在的Q标志)的值设置为已知值
•启用或禁用中断
•更改处理器模式(例如,初始化堆栈指针)
•更改加载和存储操作的字节顺序
•更改处理器状态(J和T位)

注意:
只有通过BX,BLX或BXJ指令写入CPSR才能直接更改T和J位,并且在针对异常返回的指令中,将隐式SPSR转换为CPSR。
通过直接更改T或J位来尝试进入或离开Thumb或Jazelle状态将产生不可预测的后果。
例子:
这些示例假定ARM处理器已处于特权模式。如果ARM处理器以用户模式启动,只有标志更新有效果

MRS R0,CPSR                     ;读CPSR到R0寄存器
BIC R0,R0,#0XF0000000           ;清除 the N Z C and V 标志位(R0 = R0 & !0xF0000000)
MSR CPSR_f,R0                   ;更新CPSR状态寄存器的N Z C V标志位

MRS R0,CPSR                     ;read the cpsr
ORR R0,R0,#0X80                 ;set the interrupt disabled bit
MSR CPSR_f,R0                   ; Update the contrl bits in the cpsr //interrupt(IRQ) now diabbled

MRS R0,CPSR
BIC R0,R0,#0X1F                 ; r0 = r0 & !0x1f  清除模式位
ORR R0,R0,#0X11                 ; R0 =  R0 | 0x11  设置模式为FIQ模式
MSR CPSR_c,R0                   ;更新CPSR状态寄存器控制模式位,进入FIQ模式

/>
状态寄存器访问指令列表
MRS 将PSR移动到通用寄存器
MSR 将通用寄存器移动到PSR寄存器
CPS 更改处理器状态。更改CPSR的一个或多个处理器模式和中断使能位,而不改变其他CPSR位。
SETEND  修改CPSR字节顺序E,位,而不改变CPSR中的任何其他位

处理器状态位也可以通过更新PC的各种分支(BX),加载和返回指令进行更新。
当它们用于Jazelle状态进入/退出和Thumb交互工作时,发生更改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  arm指令集 arm