Cotex-M3汇编指令集(速查以及使用)

本文详细介绍了Cortex-M3架构的汇编指令集,包括基本语法、标号、操作码、立即数处理、宏定义、数据传输、条件转移、存储器操作、TBB/TBH查表跳转等,帮助开发者理解和运用Cortex-M3的特性和限制。
摘要由CSDN通过智能技术生成

layout: post
title: “指令集”
date: 2024-1-16 15:39:08 +0800
tags: Cotex-M3 Cotex-M3权威指南笔记


指令集

基础语法

标号
	操作码操作数1,  操作数2,    ...     ;注释

标号是可选的,如果有,它必须顶格写。标号的作用是让汇编器来计算程序转移的地址。

操作码是指令的助记符,它的前面必须有至少一个空白符,通常使用一至二个“Tab”键来产生。操作码后面往往跟随若干个操作数,而第1个操作数,通常都给出本指令的执行结果存储处。不同指令需要不同数目的操作数

立即数必须以“#”开头

MOV R0,     #0x12       ; R0 <- 0x12       
MOV R1,     #’A’        ; R1 <- 字母A的ASCII码

还可以使用EQU指示字来定义常数

NVIC_IRQ_SETEN0     EQU     0xE000E100      ;注意:常数定义必须顶格写

宏定义

MOV R1, #NVIC_IRQ0_ENABLE      ; 把立即数传送到R1中

如果汇编器不能识别某些特殊指令的助记符,你就要“手工汇编”——查出该指令的确切二进制机器码,然后使用DCI编译器指示字。例如,BKPT指令的机器码是0xBE00,即可以按如下格式书写:

DCI      0xBE00    ; 断点(BKPT),这是一个16位指令

可以使用DCB来定义一串字节常数,字节常数还允许以字符串的形式来表达;还可以使用DCD来定义一串32位整数

image-20240116203814554

后缀

image-20240116203922652

image-20240116204425447

Cortex-M3中,对条件后缀的使用有很大的限制:只有转移指令(B指令)才可随意使用。

S后缀可以和条件后缀在一起使用

指令

16位数据操作

image-20240116204617818

16位转移指令

image-20240116204703960

image-20240116204715593

16位存储器数据传送

image-20240116204826031

16位其他指令

image-20240116204915325

32位数据操作

image-20240116205054520

image-20240116205156012

image-20240116205210942

32位存储器数据传送

image-20240116205250930

32位跳转

image-20240116205318700

32位其他指令

image-20240116205426173

image-20240116205510253

实际使用

数据的传送

寄存器之间的传送
MOV R8, R3
访问存储器

image-20240116205806998

image-20240116205840223

image-20240116205952196

image-20240116210022858

使用!表示自增或者自减, 如果不加!的话寄存器里面的值不会变

还可以用于更新寄存器的标志, LDR.W R0, [R1, #20]!, 先执行R1 = R1 + 20, 之后把R1位置的值放到R0(预索引)

image-20240116210636136

后索引

先把寄存器地址里面的值取出来以后再进行更新寄存器

STR.W   R0,     [R1],   #-12     ;后索引

image-20240116210812534

**注: **使用寄存器作为偏移的时候不能使用前后索引

立即数

16位指令MOV支持8位立即数加载

MOV R0,     #0x12

32位指令MOVW和MOVT可以支持16位立即数加载。

要加载32位立即数怎么办呢?如果要直来直去,当前是要用两条指令来完成了。通过组合使用MOVW和MOVT就能产生32位立即数, 必须先使用MOVW,再使用MOVT。这种顺序是不能颠倒的,因为MOVW会清零高16位

更流行的是另一种方法:使用汇编器提供的”LDR Rd, = imm32”伪指令

LDR 和 ADR伪指令

如果加载的是程序地址, 会把最低位设置为1, 加载的是数据不会设置为1

image-20240116211925600

image-20240116211933933

ADR指令不会设置为1

image-20240116212013911

数据处理

image-20240116212208406

常见的四则运算

image-20240116212254043

image-20240116212426200

常用逻辑运算

image-20240116212516599

image-20240116212702910

位移和循环

image-20240116212812315

image-20240116213237068

带符号位扩展

image-20240116213452204

数据顺序翻转

image-20240116213533972

image-20240116213550461

位段处理

image-20240116213654266

程序呼叫与跳转

  • 无条件跳转
B       Label       ;跳转到Label处对应的地址    
BX      reg         ;跳转到由寄存器reg给出的地址

reg的最低位指示出在转移后将进入的状态:是ARM(LSB=0),还是Thumb(LSB=1)。CM3只在Thumb中运行,就必须保证reg的LSB=1

  • 保存返回地址
BL      Label       ;跳转到Label对应的地址,并且把跳转前的  下条指令地址保存到LR     
BLX     reg         ;跳转到由寄存器reg给出的地址,并根据REG的LSB切换处理器状态,                        ;还要把转移前的下条指令地址保存到LR

只能保存一级, 所以在进行多层调用的时候需要对LR寄存器的值进行并保存

  • 条件转移

image-20240116221802654

主要用于跳转指令条件以及IF-Then指令的依据

image-20240116221927840

image-20240116222002050

image-20240116222309321

CMP指令。CMP指令在内部做两个数的减法,并根据差来设置标志位,但是不把差写回

CMP      R0,      R1      ; 计算R0-  R1的差,并且根据结果更新标志位   
CMP      R0,      0x12 ; 计算R0-  0x12的差,并且根据结果更新标志位

CMN是CMP的一个孪生姊妹,只是它在内部做两个数的加法(相当于减去减数的相反数)

CMN      R0,      R1      ; 计算R0+R1的和,并根据结果更新标志位  
CMN      R0,      0x12 ; 计算R0+0x12的和,并根据结果更新标志位

TST指令的内部其实就是AND指令,只是不写回运算结果,它也无条件更新标志位。

TST      R0,      R1      ; 计算R0   & R1,并根据结果更新标志位   
TST      R0,      0x12 ; 计算R0   & 0x12,并根据结果更新标志位

TEQ指令的内部其实就是EOR指令,只是不写回运算结果,它也无条件更新标志位。

TEQ      R0,      R1      ; 计算R0   ^ R1,并根据结果更新标志位   
TEQ      R0,      0x12 ; 计算R0   ^ 0x12,并根据结果更新标志位

隔离指令(存储器相关)

在进行存储器映射关系改变或者保护区的改变以后, 需要一个数据同步指令DSB

image-20240117125124501

一般情况下主要使用前两条

第三条可以在更新代码以后使用用来清空流水线

饱和运算

主要用于进行削顶失真, 原因是数字溢出以后, 会从最大变成最小, 最小变为最大

使用饱和运算以后会在到达极值以后保持极值

image-20240117130211481

image-20240117130245029

举例来说,如果要把一个32位(带符号)整数饱和到12位带符号整数(-2048至2047),则可以如下使用SSAT指令

SSAT{.W}        R1, #12,      

image-20240117130332381

如果需要把32位整数饱和到无符号的12位整数(0-4095),则可以如下使用USAT指令

USAT{.W}    R1, #12, R0

image-20240117130500683

image-20240117130522975

image-20240117130531350

其他指令

MSR/MRS特殊寄存器操控

访问特殊功能寄存器的“专用通道”, 必须在特权级下使用,除了APSR可以在用户级下访问外。

image-20240117130726748

image-20240117130811156

IF-THEN

围起一个块,里面最多有4条指令,它里面的指令可以条件执行

IT指令已经带了一个“T”,因此还可以最多再带3个“T”或者“E”。 并 且对T和E的顺序没有要求。其中T对应条件成立时执行的语句,E对应条件不成立时执行的语句。在If-Then块中的指令必须加上条件后缀,且T对应的指令必须使用和IT指令中相同的条件,E对应的指令必须使用和IT指令中相反的条件。

IT的使用形式总结如下:IT            <cond>    ;围起1条指令的IF-  THEN块
IT<x>       <cond>    ;围起2条指令的IF-  THEN块
IT<x><y>    <cond>    ;围起3条指令的IF-  THEN块
IT<x><y><z> <cond>   ;围起4条指令的IF-  THEN块

image-20240117131134348

CBZ/CBNZ比较跳转

比较并条件跳转指令专为循环结构的优化而设,它只能做前向跳转

BZ      <Rn>, <label>    
CBNZ <Rn>, <label>
while (R0!=0)    {
    Function1();    
} 
变成
Loop        
    CBZ     R0, LoopExit    
    BL   Function1
    B       Loop    
LoopExit:  
   ...

CBZ/CBNZ不会更新标志位

REV, REVH,REV16以及REVSH大小端处理

REV反转32位整数中的字节序,REVH则以半字为单位反转,且只反转低半字。语法格式为

REV      Rd,      Rm    
REVH Rd,      Rm    
REV16 Rd,      Rm    REVSH Rd,      

记R0=0x12345678

REV     R1,      R0    
REVH 	R2,      R0    
REV16 	R3,    R0 

执行后R1=0x78563412,R2=0x12347856,R3=0x34127856

专门服务于小端模式和大端模式的转换

REVSH在REVH的基础上,还把转换后的半字做带符号扩展

RBIT翻转

比前面的REV之流更精细,它是按位反转的,相当于把32位整数的二进制表示法水平旋转180度。其格式为:RBIT.W Rd, Rn

例如,记R1=0xB4E10C23(二进制数值为 1011,0100,1110,0001,0000,1100,0010,0011),``RBIT.W R0, R1`

R0=0xC430872D(二进制数值为1100,0100,0011,0000,1000,0111,0010,1101)

SXTB, SXTH, UXTB, UXTH数据扩展

为了体贴C语言的强制数据类型转换而设的,把数据宽度转换成处理器喜欢的32位长度

对于SXTB/SXTH,数据带符号位扩展成32位整数。对于UXTB/UXTH,高位清零

SXTB        R1,  R0    ; R1=0x00000065 
SXTH        R1,  R0    ; R1=0xffff8765 
UXTB        R1,  R0    ; R1=0x00000065 
UXTH        R1,  R0    ; R1=0x00008765 
BFC/BFI,UBFX/SBFX寄存器中部分数据转移

BFC(位段清零)指令把32位整数中任意一段连续的2进制位s清0,语法格式为

BFC.W       Rd,     #lsb,       #width
LDR      R0,   =0x1234FFFF 
BFC      R0,   #4, #10		R0= 0x1234C00F	

位段不支持首尾拼接。例如, BFC R0, #27, #9将产生不可预料的结果

BFI(位段插入指令),把某个寄存器按LSB对齐的数值,拷贝到另一个寄存器的某个位段中,

BFI  .W       Rd,     Rn,     #lsb,       #width
LDR         R0,      =0x12345678    
LDR         R1,      =0xAABBCCDD    
BFI.W    	R1,      R0,   #8, 

UBFX/SBFX都是位段提取指令

UBFX.W     Rd,     Rn,     #lsb,       #width
SBFX.W     Rd,     Rn,     #lsb,       #width

UBFX从Rn中取出任一个位段,执行零扩展后放到Rd中

image-20240117133157776

SBFX也抽取任意的位段,但是以带符号的方式进行扩展。

image-20240117133221456

LDRD/STRD 64位数据操作

image-20240117133512561

image-20240117133549476

TBB,TBH

TBB(查表跳转字节范围的偏移量)指令和TBH(查表跳转半字范围的偏移量)指令,分别用于从一个字节数组表中查找转移地址,和从半字数组表中查找转移地址。TBH的转移范围已经足以应付任何臭长的switch结构。如果写出的switch连TBH都搞不定,只能说那人有严重自虐倾向。

因为CM3的指令至少是按半字对齐的,表中的数值都是在左移一位后才作为前向跳转的偏移量的。又因为PC的值为当前地址+4,故TBB的跳转范围可达255*2+4=514

TBH的跳转范围更可高达65535*2+4=128KB+2

只能作前向跳转,也就是说偏移量是一个无符号整数。

TBB.W  [Rn,Rm]; PC+= Rn[Rm]*2

image-20240117134552746

image-20240117134656818

TBH的操作原理与TBB相同,只不过跳转表中的每个元素都是16位的。故而下标为Rm的元素要从Rn+2*Rm处去找。

image-20240117134717986

image-20240117135004962

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值