首页 > 编程语言 >ARM汇编——札记

ARM汇编——札记

时间:2024-07-24 17:44:40浏览次数:14  
标签:汇编 r12 r1 r2 memcpy 内存 寄存器 ARM 札记

1 __asm volatile ("dmb sy" ::: "memory")

这是一个用于ARM架构的内联汇编语句,用于实现内存屏障(Memory Barrier)操作。

  • "dmb sy": 是一个内存屏障指令,它确保在此指令之前的所有内存访问操作都执行完毕,并且对后续的内存访问操作可见。

  • "volatile": 关键字表明这是一个不会被编译器优化掉的汇编代码。

  • "memory": 表示汇编代码可能会访问或修改内存,这告诉编译器不要把汇编代码之前和之后的代码重排序。

这个语句的作用是:

  1. 确保在执行 "dmb sy" 指令之前,所有之前的内存访问操作都已经完成,并且对后续的内存访问操作是可见的。
  2. 同时,它也阻止编译器对此汇编指令前后的代码重排序。

这是一个很好的例子,展示了如何在C/C++代码中使用内联汇编来实现更精细的内存控制。

注意:汇编语言的起始表示是__asm

2 ldm

在 ARM 汇编语言中,指令 ldm r1!, {r3, r4, r5, r6, r7, r8, r12, lr} 的意思是从内存中加载多个寄存器。下面是这条指令的详细解释:

2.1 指令结构

  • ldmLoad Multiple,表示从内存中加载多个寄存器。

  • r1!:基地址寄存器 r1,使用了 ! 符号,表示使用基地址寄存器并在操作后更新它。

  • {r3, r4, r5, r6, r7, r8, r12, lr}:要加载的寄存器列表。

  • 指令含义

    ldm r1!, {r3, r4, r5, r6, r7, r8, r12, lr} 表示从内存中加载多个寄存器,具体步骤如下:

    • 加载寄存器:从内存地址 r1 开始,按顺序加载寄存器 r3 到 r12 以及链接寄存器 lr。就是将数据加载到相应的寄存器中
    • 更新基地址:加载完成后,将基地址寄存器 r1 增加,以指向加载的最后一个内存位置之后的地址。
  • 内存操作

    假设内存中从地址 r1 开始有以下内容:

    地址 内容
    0x1000 0x00000001 -> r3
    0x1004 0x00000002 -> r4
    0x1008 0x00000003 -> r5
    0x100C 0x00000004 -> r6
    0x1010 0x00000005 -> r7
    0x1014 0x00000006 -> r8
    0x1018 0x00000007 -> r12
    0x101C 0x00000008 -> lr

执行 ldm r1!, {r3, r4, r5, r6, r7, r8, r12, lr} 后,寄存器和内存将被更新为:

r3 = 0x00000001
r4 = 0x00000002
r5 = 0x00000003
r6 = 0x00000004
r7 = 0x00000005
r8 = 0x00000006
r12 = 0x00000007
lr = 0x00000008

基地址寄存器 r1 将增加 8 * 4 = 32 字节,指向 0x1020。

2.2 总结

指令 `ldm r1!, {r3, r4, r5, r6, r7, r8, r12, lr} 在 ARM 汇编语言中:

从内存地址 r1 开始加载寄存器 r3 到 lr。
每个寄存器占用 4 个字节。
更新基地址寄存器 r1,使其指向加载的最后一个内存位置之后的地址。
这条指令用于快速从内存中恢复多个寄存器的状态,常用于函数返回时恢复保存的上下文。

3 实例汇编代码分析

  0xb341f270 <+0>:	push	{r0, r4, lr}          # 将寄存器 r0, r4 和链接寄存器 lr 压入栈中,保存它们的值。
  0xb341f274 <+4>:	subs	r2, r2, #4            # 将寄存器 r2 的值减去 4。
                                                # r2 通常是传递给 memcpy 的第三个参数,表示要复制的字节数。
  0xb341f278 <+8>:	blt	0xb341f32c <memcpy+188> # 如果r2小于0(即需要复制的字节数小于4),跳转到memcpy函数的偏移量188处。
  0xb341f27c <+12>:	ands	r12, r0, #3           # 将r0源地址与3进行按位与操作,将结果存储在r12中。
                                                # 这个操作用来检查地址是否对齐。
  0xb341f280 <+16>:	pld	[r1]  # 使用PLD(预取数据)指令预取r1寄存器指向的地址的数据到缓存中,以提高后续的加载速度。
  0xb341f284 <+20>:	bne	0xb341f34c <memcpy+220> # 如果r12不为零,跳转到memcpy函数的偏移量220处。
  0xb341f288 <+24>:	ands	r12, r1, #3           # 将r1(目标地址)与3进行按位与操作,将结果存储在r12中,
                                                # 检查目标地址是否对齐。
  0xb341f28c <+28>:	bne	0xb341f37c <memcpy+268> # 如果 r12 不为零,跳转到 memcpy 函数的偏移量 268 处。
  0xb341f290 <+32>:	subs	r2, r2, #28           # 将 r2 的值减去 28,检查是否有足够的字节进行块复制。
  0xb341f294 <+36>:	push	{r5, r6, r7, r8}      # 将寄存器 r5, r6, r7 和 r8 压入栈中,保存它们的值。
  0xb341f298 <+40>:	blt	0xb341f2d0 <memcpy+96>  # 如果 r2 小于 0,跳转到 memcpy 函数的偏移量 96 处。
  0xb341f29c <+44>:	pld	[r1]                    # 再次预取 r1 指向的内存地址的数据。
  0xb341f2a0 <+48>:	subs	r2, r2, #96	; 0x60    # 将 r2 的值减去 96。
  0xb341f2a4 <+52>:	pld	[r1, #28]               # 预取 r1 加 28 的地址处的数据。
  0xb341f2a8 <+56>:	blt	0xb341f2b8 <memcpy+72>  # 如果 r2 小于 0,跳转到 memcpy 函数的偏移量 72 处。
  0xb341f2ac <+60>:	pld	[r1, #60]	; 0x3c        # 预取 r1 加 60 的地址处的数据。
  0xb341f2b0 <+64>:	pld	[r1, #92]	; 0x5c        # 预取 r1 加 92 的地址处的数据。
  0xb341f2b4 <+68>:	pld	[r1, #124]	; 0x7c      # 预取 r1 加 124 的地址处的数据。
  => 0xb341f2b8 <+72>:	ldm	r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
  • pld: pre load
  • blt: branch if less than
  • bne: branch not equal

提供的 ARM 汇编代码片段是 memcpy 函数的一部分,这部分代码负责将内存块从一个位置复制到另一个位置。让我们详细解释一下这个片段,特别是与 pc 指向的 memcpy+72 相关的部分:

指令解释
这些指令优化了内存访问,以提高 memcpy 函数的性能。特别是 PLD 指令(预取数据)用于提前加载数据到缓存中,减少后续内存访问的延迟。

memcpy+72 的含义
指令 0xb341f2b8 <+72> 是 memcpy 函数偏移 72 处的指令。根据上面的代码,blt 0xb341f2b8 <memcpy+72> 会在 r2 小于 0 时跳转到这个位置。

这意味着:

当 r2 小于 0 时,程序将跳转到 0xb341f2b8 <memcpy+72>,继续执行 memcpy 函数偏移 72 处的代码。

总结

0xb341f2b8 <memcpy+72> 处的指令是 memcpy 函数内的某个关键位置,主要是优化内存访问以提高性能。在 memcpy 函数的不同部分,程序会跳转到这个位置来执行特定的内存复制操作。如果你在 GDB 中看到程序计数器 pc 指向这个位置,意味着程序正在执行 memcpy 函数的这个优化部分。

标签:汇编,r12,r1,r2,memcpy,内存,寄存器,ARM,札记
From: https://www.cnblogs.com/gwzz/p/18321367

相关文章

  • pycharm配置及python环境相关配置
     python虚拟环境不同项目依赖的第三方包的版本可能不一样,这样一个环境就没法同时开发不同的项目,所以需要创建不同的虚拟环境virtualenv用户创建独立的python环境,多个python项目互相独立互不影响安装方法pipinstallvirtualenv创建虚拟环境virtualenvvenv会......
  • HarmonyOS资源使用
    目录文档并不完整具体看官方文档 资源使用说明应用资源资源文件介绍base目录与限定词目录访问应用资源示例 练习操作系统资源 资源分类与访问 资源分类资源目录base目录限定词目录限定词目录的命名要求资源组目录媒体资源类型说明资源文件示例创建资源......
  • PyCharm安装教程(详细步骤)
    一、软件简介PyCharm是一款PythonIDE,其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如,调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。......
  • 我可以关闭特定课程的 PyCharm 自动完成功能吗
    Pycharm中的Python有没有办法表明我不希望在自动完成窗口中向用户显示特定类的类型提示?我有一个类Result可能包含字符串,例如1+2或另一个类的实例ExerciseExercise类包含2个数字,可以从中生成一个练习字符串。Result类......
  • 【攻防世界】warmup
    warmup(反序列化与sql注入)题目来源攻防世界NO.GFSJ0999题目描述题目提示:平平无奇的输入框打开网址页面如下,没有有用信息。题目给了附件,直接下载,得到源码如下:index.php(其中页面布局等无用代码省略)<?phpinclude'conn.php';include'flag.php';if(isset($_......
  • PyCharm 中的 ndb Google Cloud Datastore 的类型提示丢失
    ndbModel类的实例对象没有类型提示。例如some_datetime不显示任何类型提示。类型提示在其他地方起作用。我是否需要安装专门用于类型提示的东西才能与ndb库一起使用?fromgoogle.cloudimportndbclassMyModel(ndb.Model):some_datet......
  • harmonyOS Next 实现验证码功能遇到的坑
    前言第一次写博记录学习harmonyOS开发的过程,文案功底差请见谅!场景刚开始学习harmonyOS开发,近期有一个翻译网报APP的需求,在登录的时候需要验证码过滤验证码机器人试错。参考https://blog.csdn.net/zcczero/article/details/137057040  感谢zcczero 大神的帖子可以直接拿......
  • .py-script 仅通过终端运行,而不是通过 Pycharm 的“运行”按钮运行
    我使用虚拟环境在PyCharm中创建了一个新的Python项目。这是我第一次使用虚拟环境,而且我还是Python和PyCharm的初学者。由于某种原因,Python无法再找到任何包,即使我确信我在虚拟环境中安装了scikit-learn。使用终端时,只要我使用源代码激活虚拟环境,一切都会正常工作........
  • 探索PyCharm的单元测试配置:提升代码质量的秘诀
    探索PyCharm的单元测试配置:提升代码质量的秘诀在软件开发过程中,单元测试是确保代码质量的关键环节。PyCharm,作为广受开发者喜爱的集成开发环境(IDE),提供了强大的单元测试支持。本文将详细介绍如何在PyCharm中配置单元测试,包括创建测试用例、运行测试、以及分析测试结果。通过......
  • 读书笔记:汇编语言(王爽)实验七
    最近读完了第八章,这道题是一个不错的总结,记录下。原题是21年的数据,这里简化为6年。代码如下:assumecs:codesgdatasegmentdb'1975','1976','1977','1978','1979','1980'dd16,22,382,1356,2390,8000dw3,7,9,13,28,38dataendst......