嵌入式学习笔记(三)

比较指令

c 复制代码
CMP : 比较两个数的大小
------------------------------

<opcode>{cond}   Rn, oprand_shifer
        
    1. 功能:比较两个数的大小

    2. 本质:比较指令的本质做减法运算   Rn - oprand_shifer

    3. 比较指令没有目标寄存器,指令的执行结果影响的是CPSR的NZCV位,
         并且不需要加S

    4. 比较指令经常和条件码配合使用,实现汇编指令的有条件执行。
------------------------------------------------------------------

---------------------------------
 /* 5. 比较指令 */
 mov r0, #15
 mov r1, #9
 
 @ 比较r0和r1寄存器中的值的大小,

 @ 如果r0 > R1 , 则r0 = r0 - r1

 @ 如果r0 < R1 , 则r1 = r1 - r0
 
 cmp r0, r1		@ r0 - r1 
 subhi r0, r0, r1
 subcc r1, r1, r0

----------------------------

hi和cc类似于if分支语句判断是否符合条件,符合执行,否则不执行;
---------------------------------------------------------------

数据搬移指令

c 复制代码
指令格式
------------------

<opcode>{Cond}{S}  Rd, oprand_shifter
        
    mov : 将第二个操作数直接赋值给目标寄存器
    
    mvn : 将第二个操作数按位取反,然后再赋值给目标寄存器

------------------------------------------------------
指令测试代码
--------------
 @ 第二个操作数是一个立即数,立即数前需要加#

 mov r0, #0xFF 	@ 功能 : R0 = 0xFF
 
 @ 第二个操作数是一个普通寄存器

 mov r1, r0		@ 功能 : R1 = R0 = 0xFF
 
 mvn r2, #0xFF   @ 功能 : R2 = ~0xFF = 0xFFFF_FF00
 
 mvn r3, r2		@ 功能 : R3 = ~R2 = 0x0000_00FF
----------------------------------------------------------

ldr伪指令
----------------
指令码:ldr
指令格式:
     ldr  Rd, =number(可以是0-4G之间的任意数)
指令代码:
     ldr r0, =0x12345678


-------------------------------------

算数运算指令

c 复制代码
指令码
----------

add :	普通加法指令,不需要考虑进位标志位(C位)

adc :	带进位的加法指令,需要考虑进位标志位(C位)

sub :   普通减法指令,不需要考虑借位标志位(C位)

sbc :	带借位的减法指令,需要考虑借位标志位(C位)

mul :	乘法指令

div :	除法指令(ARM-v8之后的架构支持除法指令)
-------------------------------------------------------




测试代码
----------------------------
/*4. 算数运算指令 */

 /* 案例1:实现两个64位数据的加法运算

    第1个64位数据,低32位保存到R0中,高32位保存到R1中;

    第2个64位数据,低32位保存到R2中,高32位保存到R3中;

    运算结果:低32位保存到R4中,高32位保存到R5中; */
    
    @ 1. 准备2个64位数据
    mov r0, #0xFFFFFFFE  @ 第1个64位数据的低32位

    mov r1, #0x5   @ 第1个64位数据的高32位

    mov r2, #0x6   @ 第2个64位数据的低32位

    mov r3, #0x7   @ 第2个64位数据的高32位
    
 @ 低32位的加法运算

 adds r4, r0, r2   @ r4 = r0 + r2 = 0x0000_0004
-------------------------------------------------------
C[29] :
-----------------
    加法:产生进位时,C位被自动置1,否则清0.

     进位:低32位向高32位进位

    减法:产生借位时,C位被自动清0,否则置1.

     借位:低32位向高32位借位
--------------------------------------
{S} : 状态标志(add"s")

        指令加S, 指令的执行结果影响CPSR的NZCV位

        指令不加S, 指令的执行结果不影响CPSR的NZCV位
----------------------------------------------------
 
 @ 高32位的加法运算  @ r5 = r1 + r3 + C = 0x0000_000D
 adc r5, r1, r3
    
 /* 案例1:实现两个64位数据的减法运算

    第1个64位数据,低32位保存到R0中,高32位保存到R1中;

    第2个64位数据,低32位保存到R2中,高32位保存到R3中;

    运算结果:低32位保存到R4中,高32位保存到R5中; */

 @ 1. 准备2个64位数据

    mov r0, #0x4   @ 第1个64位数据的低32位

    mov r1, #0xF   @ 第1个64位数据的高32位

    mov r2, #0x6   @ 第2个64位数据的低32位

    mov r3, #0x7   @ 第2个64位数据的高32位
 
 @ 低32位减法运算

 subs r4, r0, r2        @ r4 = r0 - r2 = 0xFFFF_FFFE

 sbc  r5, r1, r3        @ r5 = r1 - r3 - !C = 0x0000_0007
----------------------------------------
@!C (产生借位时,C位被自动清0) = 1
----------------------------------------
 
 @ 案例3:乘法指令

 mov r0, #3

 mov r1, #4

 mul r2, r0, r1    @ r2 = r0 * r1 = 0xC
 
 @ 乘法指令的第二个操作数只能是一个寄存器

 @ mul r3, r0, #5  @ Error

位运算指令

c 复制代码
指令码
------------

and : 按位与(&)

orr : 按位或(|)

eor : 按位异或(^)

bic : 按位清除的指令
    
口诀:
    与0清0,与1不变
    或1置1,或0不变
    异或1取反,异或0不变
----------------------------------


测试代码
----------------
/* 3. 位运算指令 */
 @ 练习题:

 @ 给定一个无符号的32位的整数,如下:

 ldr r0, =0x12345678

 @ 对r0寄存器中的位的值进行以下操作,要求保证其他位不变。
 @31                                     0
 @**** **** **** **** **** **** **** ****
 
 @ 1. 将r0寄存器的第[7]位置1,保证其他位不变

 orr r0, r0, #0x80
    orr r0, r0, #(0x1 << 7)    @  orr r0, r0, #(1 << 7)
        
 @ 2. 将r0寄存器的第[29]位清0,保证其他位不变

 and r0, r0, #0xdFFFFFFF
    and r0, r0, #(~(0x1 << 29))
              
 @ 3. 将r0寄存器的第[25:20]位置1,保证其他位不变

 orr r0, r0, #(0x3F << 20)
        
 @ 4. 将r0寄存器的第[18:12]位清0,保证其他位不变

 and r0, r0, #(~(0x7F << 12))
        
 @ 5. 将r0寄存器的第[11:4]位修改为0b0110 1101, 保证其他位不变
        
    @ 5.1 > 先整体将对应的位清0
    and r0, r0, #(~(0xFF << 4))
    @ 5.2 > 再将对应的位置1
 orr r0, r0, #(0x6D << 4)		@ 常用的用法
 
 @ 5.1 > 先整体将对应的位置1
    orr r0, r0, #(0xFF << 4)
    @ 5.2 > 再将对应的位清0
 and r0, r0, #(~(0x92 << 4))		@ 不使用这种用法
 
 
 @ 6. bic指令:按位清0

 @ 第二个操作数的哪位为1,就将第一个操作数中的值哪位1清0,

 @ 然后将结果写回到目标寄存器中

 bic r0, r0, #(0x1 << 7)  @ 将r0寄存器中的值的第[7]位清0

 bic r0, r0, #(0xFF << 8) @ 将r0寄存器中的值的第[15:8]位清0
 
 @ 如果第一个寄存器和目标寄存器的编号相同时,可以合并写一个

 orr r0, #(0x1 << 7)		@ R0 |= (0x1 << 7)

移位操作指令

c 复制代码
指令码
-------------
lsl : 逻辑左移/无符号数左移

lsr : 逻辑右移/无符号数右移

asr : 算数右移/有符号数右移

ror : 循环右移
----------------------------------



指令格式
-----------------
<opcode>{Cond}{S}  Rd, Rn, oprand_shifter
----------------------------------------------



指令测试代码
-----------------------
/* 2. 移位操作指令 */

 ldr r0, =0x0000FFFF
 
 @ 将R0中的值左移4位,结果写到R1中

 @ 逻辑左移:高位移出,低位补0

 lsl r1, r0, #4  @ R1 = R0 << 4 = 0x000FFFF0
 
 @ 将R0中的值右移4位,结果写到R2中

 @ 逻辑右移:低位移出,高位补0

 lsr r2, r0, #4  @ R2 = R0 >> 4 = 0x00000FFF
 
 @ 将R0中的值算数右移4位,结果写到R3中

 @ 算数右移:低位移出,高位补符号位

 asr r3, r0, #4  @ R3 = R0 >> 4 = 0x00000FFF
 
 @ 将R0中的值循环右移4位,结果写到R4中

 @ 循环右移:低位移出,补到高位

 ror r4, r0, #8      @ r4 = R0 >> 8 = 0xFF0000FF
 
 
 mov r0, #-0xFF
 asr r5, r0, #4
 
 mov r0, #(0xFF << 4)    @ R0 = 0xFF << 4 = 0xFF0
 mov r2, #~(0xFF << 4)   @ R0 = ~(0xFF << 4) = 0xFFFFF00F
        
 @ 第二个操作数是一个经过移位操作的寄存器

 mov r1, r0, lsr #4     @ R1 = r0 >> 4 = 0xFF
相关推荐
V+zmm101349 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
oneouto12 分钟前
selenium学习笔记(二)
笔记·学习·selenium
sealaugh3217 分钟前
aws(学习笔记第十九课) 使用ECS和Fargate进行容器开发
笔记·学习·aws
Oneforlove_twoforjob35 分钟前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-131437 分钟前
常用的缓存技术都有哪些
java
炭烤玛卡巴卡44 分钟前
学习postman工具使用
学习·测试工具·postman
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
thesky1234561 小时前
活着就好20241224
学习·算法
蜗牛hb1 小时前
VMware Workstation虚拟机网络模式
开发语言·学习·php
汤姆和杰瑞在瑞士吃糯米粑粑2 小时前
【C++学习篇】AVL树
开发语言·c++·学习