ARM 汇编指令集——汇编中三种符号(汇编指令、伪指令、伪操作)、汇编基本格式、数据操作指令、跳转指令、特殊功能寄存器操作指令、内存操作指令、混合编程

2023-09-16 15:41:57

目录

一、汇编中三种符号(汇编指令、伪指令、伪操作)

二、汇编基本格式

三、数据操作指令

3.1 数据搬移指令mov/mvn

① 示例

② 立即数

3.2 移位操作指令lsl/lsr/asr/ror

示例

3.3 位运算操作指令and/orr/eor/bic

① 示例1

② 示例2

3.4 算数运算操作指令add/adc/sub/sbc/mul

① 实现两个64位数相加

② 实现两个64位数相减

③ 乘法指令

3.5 比较指令cmp

① 条件指令

② 示例

四、跳转指令

① 练习

五、特殊功能寄存器操作指令

六、内存操作指令

6.1 单寄存器操作指令

① 读写代码练习

② 特殊读写格式

③ 验证keil软件存储方式

6.2 多寄存器操作指令

① 练习

6.3 栈指针操作指令

① 满压栈、空增栈压入数据过程

② 练习代码1

③ 栈使用场合1

④ 栈使用场合2

七、混合编程

7.1 汇编调用C

汇编文件编写

C函数编写

7.2 C调用汇编

汇编启动文件编写:start.s文件

C语言main函数入口:main.c文件

汇编实现加法函数编写:add.s文件

7.3 内联汇编

八、总结


一、汇编中三种符号(汇编指令、伪指令、伪操作)

二、汇编基本格式

三、数据操作指令

3.1 数据搬移指令mov/mvn

① 示例

② 立即数

0xff000000 =====>判断的数
1111 1111 0000 0000 0000 0000 0000 0000   =====>判断的数
0000 0000 0000 0000 0000 0000 1111 1111  =====>找到0xff这个数 =====> 循环右移8位

0xf0000000 =====>判断的数
1111 0000 0000 0000 0000 0000 0000 0000   =====>判断的数
0000 0000 0000 0000 0000 0000 0000 1111  =====>找到0xf这个数 =====> 循环右移4位

0xf000000f =====>判断的数
1111 0000 0000 0000 0000 0000 0000 1111   =====>判断的数
0000 0000 0000 0000 0000 0000 1111 1111  =====>找到0xff这个数 =====> 循环右移4位

0x1FE00000=====>判断的数
0001 1111 1110 0000 0000 0000 0000 0000   =====>判断的数
0000 0000 0000 0000 0000 0000 1111 1111  =====>找到0xff这个数 =====> 循环右移11位

0x1F800000=====>判断的数
0001 1111 1000 0000 0000 0000 0000 0000   =====>判断的数
0000 0000 0000 0000 0000 0000 0111 1110  =====>找到0x7E这个数 =====> 循环右移10位

3.2 移位操作指令lsl/lsr/asr/ror

示例

    mov r0,#0xff
    
    @ 1.将r0寄存器中的值,逻辑左移4位,赋值给目标寄存器r1,值  
    lsl r1,r0,#0x4 @ r1 = r0 << 4 = 0xff0
    @ 0000 0000 0000 0000 0000 0000 1111 1111
    @ 0000 0000 0000 0000 0000 1111 1111 0000 
    
    @ 2.将r1寄存器中的值,逻辑右移4位,赋值给目标寄存器r2,值  r2 = r1 >> 4
    lsr r2,r1,#0x4  @ r2 = r1 >> 4 = 0xff
    @ 0000 0000 0000 0000 0000 1111 1111 0000 
    @ 0000 0000 0000 0000 0000 0000 1111 1111  
    
    @ 3.将r2寄存器中的值,循环右移4位,赋值给目标寄存器r3,值 
    ror r3,r2,#0x4 @ r3 = 0xf000000f
    @ 0000 0000 0000 0000 0000 0000 1111 1111 
    @ 1111 0000 0000 0000 0000 0000 0000 1111  
    
    ldr r4,=0x800000ff
    @ 4.将r4寄存器中的值,算数右移4位,赋值给目标寄存器r5,值
    asr r5,r4,#0x4  @ r5 = 0xf800000f
    @ 1000 0000 0000 0000 0000 0000 1111 1111 
    @ 1111 1000 0000 0000 0000 0000 0000 1111

3.3 位运算操作指令and/orr/eor/bic

① 示例1

② 示例2

3.4 算数运算操作指令add/adc/sub/sbc/mul

① 实现两个64位数相加

@第一个64位数:高32位用r0表示0x3   低32位用r1表示0xffffffff
@第二个64位数:高32位用r2表示0x4   低32位用r3表示0x1
@实现两个64位数相加:高32位相加r4,低32位相加r5    
    ldr r0,=0x3
    ldr r1,=0xffffffff
    ldr r2,=0x4
    ldr r3,=0x1
    adds r5,r1,r3 @ r5 = r1 + r3 = 0xffffffff + 0x1 = 0x0 ===> add 影响CPSR寄存器的C位
    adc r4,r0,r2 @ r4 = r0 + r2 = 0x3 + 0x4 + C  = 0x8 ===> adc    

② 实现两个64位数相减

    @第一个64位数:高32位用r0表示0x7   低32位用r1表示0x4
    @第二个64位数:高32位用r2表示0x4   低32位用r3表示0x5
    @实现两个64位数相减法:高32位相加r4,低32位相加r5
      
    ldr r0,=0x7
    ldr r1,=0x4
    ldr r2,=0x4
    ldr r3,=0x5
    subs r5,r1,r3 @ r5 = r1 - r3 = 0x4 - 0x5 = 0xffffffff ===> sub 影响CPSR寄存器的C位
    sbc r4,r0,r2  @ r4 = r0 - r2 = 0x7 - 0x4 - !C  = 0x2 ===> sbc 

③ 乘法指令

3.5 比较指令cmp

① 条件指令

② 示例

四、跳转指令

① 练习

五、特殊功能寄存器操作指令

六、内存操作指令

6.1 单寄存器操作指令

① 读写代码练习

② 特殊读写格式

    ldr r0,=0x40000800 @ 准备一块地址空间
    ldr r1,=0x11111111 @ r1 = 0x11111111
    ldr r2,=0x22222222 @ r1 = 0x22222222
    ldr r3,=0x33333333 @ r1 = 0x33333333
    
    @仿真时,思考1)寄存器写到哪一块地址空间中,2)观察r0寄存器中的值变化
    
    @将r1寄存器中的值,写到r0+4地址空间中,r0寄存器中的值没有发生变化
    @ [0x40000804] = 0x11111111 r0 = 0x40000800
        str r1,[r0,#4]
    
     
    @将r2寄存器中的值,写到r0地址空间中,r0寄存器中的值+4
    @ [0x40000800] = 0x22222222 r0 = 0x40000804    
        str r2,[r0],#4
    
    @将r3寄存器中的值,写到r0+4地址空间中,r0寄存器中的值+4
    @ [0x40000808] = 0x33333333 r0 = 0x40000808
        str r3,[r0,#4]!

③ 验证keil软件存储方式

6.2 多寄存器操作指令

① 练习

6.3 栈指针操作指令

① 满压栈、空增栈压入数据过程

② 练习代码1

③ 栈使用场合1

    ldr sp,=0x40000800 @ 准备一块地址空间
    mov r0,#0x1  @ r0 = 0x1
    mov r1,#0x2  @ r1 = 0x2
    bl add1_func  @ 跳转到add1_func函数
    add r0,r0,r1 @ r0 = r0 + r1 = 0x3
    b stop
    
add1_func:
    @ 压栈保存现场  r0 = 0x1 r1 = 0x2
    stmfd sp!,{r0-r1}
    mov r0,#0x3  @ r0 = 0x3
    mov r1,#0x4  @ r1 = 0x4
    add r0,r0,r1 @ r0 = r0 + r1 = 0x7
    @ 出栈保存现场  r0 = 0x1 r1 = 0x2
    ldmfd sp!,{r0-r1}
    mov pc,lr @ pc = lr

④ 栈使用场合2

_start:  @指定汇编中函数入口
    
    ldr sp,=0x40000800 @ 准备一块地址空间
    mov r0,#0x1  @ r0 = 0x1
    mov r1,#0x2  @ r1 = 0x2
    bl add1_func  @ 跳转到add1_func函数,保存函数返回地址到LR寄存器中
    add r0,r0,r1 @ r0 = r0 + r1 = 0x3
    b stop
    
add1_func:
    @ 压栈保存现场  r0 = 0x1 r1 = 0x2
    stmfd sp!,{r0-r1,lr}
    mov r0,#0x3  @ r0 = 0x3
    mov r1,#0x4  @ r1 = 0x4
    bl  add2_func @跳转到add2_func函数,保存函数返回地址到LR寄存器中
    add r0,r0,r1 @ r0 = r0 + r1 = 0x7
    @ 出栈保存现场  r0 = 0x1 r1 = 0x2
    ldmfd sp!,{r0-r1,pc}
    
add2_func:
    @ 压栈保存现场  r0 = 0x3 r1 = 0x4
    stmfd sp!,{r0-r1}
    mov r0,#0x5  @ r0 = 0x5
    mov r1,#0x6  @ r1 = 0x6
    add r0,r0,r1 @ r0 = r0 + r1 = 0xB    
    @ 出栈保存现场  r0 = 0x3 r1 = 0x4
    ldmfd sp!,{r0-r1}
    mov pc,lr

七、混合编程

7.1 汇编调用C

汇编文件编写

        ldr sp,=0x40000800 @ 初始化栈指针
        mov r0,#0x1
        mov r1,#0x2
        mov r2,#0x3
        mov r3,#0x4
        bl add_func      

C函数编写

int add_func(int a,int b,int c,int d)
{
      return (a+b+c+d);
}   

7.2 C调用汇编

汇编启动文件编写:start.s文件

        ldr sp,=0x40000800  @ 初始栈指针
        b main  @ 跳转到C函数入口

C语言main函数入口:main.c文件

int sum1 = 0;

int add1_func(int a,int b,int c,int d);

int main()
{
    sum1 = add1_func(1,2,3,4);
      while(1);
     return 0;
}

汇编实现加法函数编写:add.s文件

@ 实现r0-r3相加,并且通过r0返回
.text
.global add1_func
add1_func:
        add r0,r0,r1
        add r0,r0,r2
        add r0,r0,r3
        mov pc,lr
.end

7.3 内联汇编

八、总结

更多推荐

PyTorch中的pyi檔案生成機制

PyTorch中的pyi檔案生成機制前言pyi檔由py生成pyi.in由pyi.in生成pyitorch/CMakeLists.txttools/pyi/gen_pyi.pygen_pyinative_functionsrand.names&rand.names_outrand.generator_with_names

Linux文件编程(lseek函数和stat函数)

文章目录前言一、lseek函数二、stat函数总结前言本篇文章来讲解lseek函数和stat函数,lseek函数主要用来设置文件偏移量,stat函数主要用来获取文件属性。一、lseek函数lseek函数用于在打开的文件中移动文件指针的位置。它可以用于设置文件的读写位置或查找特定位置的数据。函数原型如下:#include

Linux 系统下 CMake 示 例

CMake是一个开源的跨平台工具,可以构建、测试和打包软件。它具有如下特性:自动搜索可能需要的程序、库和头文件的能力;独立的构建目录(如build),可以安全清理;支持复杂的自定义命令(下载、生成各种文件);自定义配置可选组件;从简单的文本文件(CMakeLists.txt)自动生成工作区和项目的能力;在主流平台上自动

Linux之Shell进阶(变量和条件判定语句)

文章目录变量变量的含义变量的定义与使用(重点)只读变量接收用户输入删除变量条件判断语句变量变量的含义什么是量?量就是数据.什么是变量?数据可以发生改变就是变量。在一个脚本周期内,其值可以发生改变的量就是变量。什么叫做一个脚本周期?一个脚本周期我们可以简单的理解为当前的shell文件。变量是shell中不可或缺的一部分,

C#中的方法

引言在C#编程语言中,方法是一种封装了一系列可执行代码的重要构建块。通过方法,我们可以将代码逻辑进行模块化和复用,提高代码的可读性和可维护性。本文将深入探讨C#中的方法的定义、参数传递、返回值、重载、递归等方面的知识,并结合实际案例介绍方法的应用。方法的定义和调用:1.1方法是什么:方法是一个包含一组语句的代码块,用于

学习python和anaconda的经验

PYTHON1常用命令1.11.1注释Python注释多行的方法有以下三种:使用ctrl+/实现多行注释、在每一行的开头使用shift+#键、输入’‘’‘’'或者"“”“”",将要注释的代码插在中间1.2definit():函数区分两个函数:1.definit(self):这种形式在__init__方法中,只有一个se

【LeetCode-面试经典150题-day24】

目录35.搜索插入位置74.搜索二维矩阵162.寻找峰值33.搜索旋转排序数组35.搜索插入位置题意:给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为O(logn)的算法。【输入样例】nums=[1,3,5,6],target

Linux性能调优 —— 内存篇

Linux性能调优——内存篇Linux内存的工作原理内存映射的概念虚存空间分布内存分配与回收分配回收内存查看与分析查看内存使用情况命令:free命令:vmstat命令:top分析单个进程命令:ps-pLinux内存的工作原理内存映射的概念大多数计算机用的主存都是动态随机访问内存(DRAM),只有内核才可以直接访问物理内

Android ANR问题触发机制

1Anr类型​Anr一般有四种类型。1.1inputdispatchingtimeout​主要时按键或触摸屏事件在5s内没有响应。这个时间在ActivityManagerService中定义。C:\Users\wangjie\AppData\Local\Android\Sdk\sources\android-32\co

设计模式:中介者模式

目录组件代码示例源码中的使用优缺点总结:中介者模式(MediatorPattern)是一种行为型设计模式,它通过封装一组对象之间的交互,来减少对象之间的直接耦合。中介者模式通过引入一个中介者对象,将对象之间的通信转化为与中介者的交互,从而降低了对象之间的依赖关系。在中介者模式中,对象之间的通信通过中介者进行,而不是直接

API商品数据接口:实现电子商务应用程序的核心功能

随着电子商务的飞速发展,许多电商平台都提供了应用程序接口(API),允许开发者调用特定的功能,如商品查询、购物车管理、订单处理以及支付等。这些API为开发者提供了在应用程序中嵌入电商功能的机会,从而为用户提供更加便捷的购物体验。本文将深入探讨API商品数据接口的相关概念、实现方法和典型案例。一、API商品数据接口概述A

热文推荐