ARM 汇编:存储上的自动递增寄存器

2024-01-20

是否可以使用 STR 自动递增寄存器的基地址[Rn]!?我仔细阅读了文档,但未能找到明确的答案,主要是因为命令语法同时适用于 LDR 和 STR - 理论上它应该适用于两者,但我找不到任何 auto 的示例- 在商店上递增(加载正常)。

我编写了一个小程序,将两个数字存储在向量中。完成后的内容out应该{1, 2}但存储会覆盖第一个字节,就好像自动增量不起作用一样。

#include <stdio.h>

int main()
{
        int out[]={0, 0};
        asm volatile (
        "mov    r0, #1          \n\t"
        "str    r0, [%0]!       \n\t"
        "add    r0, r0, #1      \n\t"
        "str    r0, [%0]        \n\t"
        :: "r"(out)
        : "r0" );
        printf("%d %d\n", out[0], out[1]);
        return 0;
}

编辑: 虽然答案对于常规加载和存储是正确的,但我发现优化器搞乱了向量指令(例如 vldm/vstm)的自动增量。例如,下面的程序

#include <stdio.h>

int main()
{
        volatile int *in = new int[16];
        volatile int *out = new int[16];

        for (int i=0;i<16;i++) in[i] = i;

        asm volatile (
        "vldm   %0!, {d0-d3}            \n\t"
        "vldm   %0,  {d4-d7}            \n\t"
        "vstm   %1!, {d0-d3}            \n\t"
        "vstm   %1,  {d4-d7}            \n\t"
        :: "r"(in), "r"(out)
        : "memory" );

        for (int i=0;i<16;i++) printf("%d\n", out[i]);
        return 0;
}

编译为

g++ -O2 -march=armv7-a -mfpu=neon main.cpp -o main

将会在最后 8 个变量的输出上产生乱码,因为优化器保留增量变量并将其用于 printf。换句话说,out[i]实际上是out[i+8],因此前 8 个打印值是向量中的最后 8 个值,其余的是超出范围的内存位置。

我尝试过不同的组合volatile整个代码中的关键字,但只有当我使用-O0标志或者如果我使用易失性向量而不是指针和新的,就像

volatile int out[16];

对于存储和加载,您可以这样做:

ldr r0,[r1],#4
str r0,[r2],#4

无论您在末尾放置什么,在本例中为 4,都会在寄存器用于地址之后但在指令完成之前添加到基址寄存器(ldr 示例中的 r1 和 str 示例中的 r2),它非常类似于

unsigned int a,*b,*c;
...
a = *b++;
*c++ = a;

编辑,您需要查看反汇编以查看发生了什么(如果有)。我正在使用最新的代码源,或者现在只是来自导师图形工具链的精简版源。

arm-none-linux-gnueabi-gcc(Sourcery CodeBench Lite 2011.09-70)4.6.1

#include <stdio.h>
int main ()
{
        int out[]={0, 0};
        asm volatile (
        "mov    r0, #1          \n\t"
        "str    r0, [%0], #4       \n\t"
        "add    r0, r0, #1      \n\t"
        "str    r0, [%0]        \n\t"
        :: "r"(out)
        : "r0" );
        printf("%d %d\n", out[0], out[1]);
        return 0;
}


arm-none-linux-gnueabi-gcc str.c -O2  -o str.elf

arm-none-linux-gnueabi-objdump -D str.elf > str.list


00008380 <main>:
    8380:   e92d4010    push    {r4, lr}
    8384:   e3a04000    mov r4, #0
    8388:   e24dd008    sub sp, sp, #8
    838c:   e58d4000    str r4, [sp]
    8390:   e58d4004    str r4, [sp, #4]
    8394:   e1a0300d    mov r3, sp
    8398:   e3a00001    mov r0, #1
    839c:   e4830004    str r0, [r3], #4
    83a0:   e2800001    add r0, r0, #1
    83a4:   e5830000    str r0, [r3]
    83a8:   e59f0014    ldr r0, [pc, #20]   ; 83c4 <main+0x44>
    83ac:   e1a01004    mov r1, r4
    83b0:   e1a02004    mov r2, r4
    83b4:   ebffffe5    bl  8350 <_init+0x20>
    83b8:   e1a00004    mov r0, r4
    83bc:   e28dd008    add sp, sp, #8
    83c0:   e8bd8010    pop {r4, pc}
    83c4:   0000854c    andeq   r8, r0, ip, asr #10

so the

sub sp, sp, #8

就是分配两个本地int out[0]和out[1]

mov r4,#0
str r4,[sp]
str r4,[sp,#4]

是因为它们被初始化为零,然后是内联汇编

8398:   e3a00001    mov r0, #1
839c:   e4830004    str r0, [r3], #4
83a0:   e2800001    add r0, r0, #1
83a4:   e5830000    str r0, [r3]

然后是 printf:

83a8:   e59f0014    ldr r0, [pc, #20]   ; 83c4 <main+0x44>
83ac:   e1a01004    mov r1, r4
83b0:   e1a02004    mov r2, r4
83b4:   ebffffe5    bl  8350 <_init+0x20>

现在很清楚为什么它不起作用了。你没有声明为不稳定的。您没有给代码返回 ram 来获取 printf 的 out[0] 和 out[1] 的值,编译器知道 r4 包含 out[0] 和 out[1] 的值,那里该函数中的代码非常少,因此不必逐出 r4 并重用它,因此它使用 r4 作为 printf。

如果你把它改成易失性的

    volatile int out[]={0, 0};

然后你应该得到想要的结果:

83a8:   e59f0014    ldr r0, [pc, #20]   ; 83c4 <main+0x44>
83ac:   e59d1000    ldr r1, [sp]
83b0:   e59d2004    ldr r2, [sp, #4]
83b4:   ebffffe5    bl  8350 <_init+0x20>

printf 的准备工作是从 ram 读取的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ARM 汇编:存储上的自动递增寄存器 的相关文章

随机推荐

  • npm 用于 javascript 客户端代码

    我正在读一份关于npm 开发者指南 https npmjs org doc developers html 我想知道是否可以使用 javascript css html 编写 Web 客户端应用程序 通过使用 npm 如果是的话 githu
  • Win32同步

    我正在尝试编写一个应用程序 基于控制台 其中一个线程从控制台读取信息 另一个线程将相同的信息打印回控制台 我陷入了实现同步逻辑的困境 谁能给我推荐一些样品 john 如果你指的是 c 你可以在这里找到示例 使用临界区对象 http msdn
  • 当我向项目添加文件时,为什么 Visual Studio 会检出 .vspscc 文件?

    如果我将新文件添加到 TFS 源代码控制下的项目 它将检出该项目文件以及该项目文件对应的 vspscc 文件 项目文件本身发生更改 以包含新文件 但 vspscc 文件根本没有更改 何必费力去检查呢 有没有办法禁止它被签出 如果有 我应该吗
  • 来自 Process.MainWindowHandle 的 C# HwndSource

    我试图 挂钩 窗口的消息来检测最小化 最大化 我环顾四周 认为执行此操作的唯一 最佳解决方案是挂钩窗口的消息 并检查 WM WINDOWPOSCHANGED 消息 然后检查其状态 我遇到了问题 System Windows Interop
  • 如何使用 Oracle 和 SQL Server 将 .NET 4.5 C# Entity Framework 6 中的列映射为大写?

    我正在使用 C NET 4 5 和实体框架 http en wikipedia org wiki ADO NET Entity Framework我的项目中有 6 个 它使用 Oracle 和 SQL Server 具体取决于客户端的安装
  • Linq to SQL DataContext Windsor IoC内存泄漏问题

    我有一个 ASP NET MVC 应用程序 它使用 Castler Windsor IoC 根据每个 Web 请求创建 Linq2SQL 数据上下文 由于某些我不完全理解的原因 每次创建新的数据上下文 在每个 Web 请求上 时 都会占用大
  • 为什么“​”被注入到我的 HTML 中?

    编辑 您可以看到问题here http project gauss appspot com 查看源代码 EDIT2 有趣的是not源码中的问题 仅适用于控制台 Firebug 也是如此 我在名为的文件中有以下标记test html h3 T
  • win32 c++ 在没有子类化的情况下检测编辑控件中的“输入”?

    基本上 我想要一个 Enter 来触发一条消息 当编辑控件获得焦点并且用户按下 Enter 时 我可以捕获该消息 网上所有的解决方案似乎都是关于子类化的 但我想知道是否还有其他方法可以解决这个问题 例如 我的按钮有一个标识符 ID BUTT
  • 如何自定义 Google 表格中答案为“是”时连接的标头值的顺序

    我怎样才能修改这个方程谷歌电子表格 https docs google com spreadsheets d 1tHL2IdijLaAD5my7m4a1uaiXNleb6Z1bI7x HPXfAVI edit usp sharing我发现这
  • Jar 签名者和 Apk 签名者有什么区别?

    由于 ApkSigner 在 Android SDK 构建工具的修订版 24 0 3 及更高版本中可用 我有一个问题 ApkSigner 和 JarSigner 之间有什么区别 为什么我们需要 ApkSigner 我可以在命令行中为两个签名
  • Swift:什么是 .swift-version 文件?

    我看到很多项目的根目录中有这个文件 swift 版本 以下是一些示例 https github com hackiftekhar IQKeyboardManager https github com hackiftekhar IQKeybo
  • 如何获取数字形式的单选按钮值

    有没有办法以整数形式获取单选按钮的值 我正在提交一个表单 但我从单选按钮获得的值始终是一个字符串 我尝试了很多解决方案 但没有一个有效 div class form check form check inline div
  • Firebase 数据不显示在 flutter 应用程序中

    我正在尝试在使用 flutter 制作的应用程序中使用 Firebase 显示数据 这一直有效直到几个小时前 之后尽管我的代码没有发生任何变化 它仍然停止工作 我收到以下警告 W DynamiteModule 3174 Local modu
  • jquery mobile url 参数未在浏览器中更新,但使用“data-url”获取正确的参数

    我创建了以下示例来展示我所经历的情况 如果我使用 Page 2a 按钮从第 1 页导航到第 2 页 则 URL 将按预期为 page2 is a 当我单击按钮返回第 1 页 然后导航到第 2b 页时 URL 仍会显示 page2 id a
  • 如何将 Tomcat 的 context.xml 中的属性注入到 Seam 组件中?

    Seam 文档会让您相信 如果您在 web xml 中定义一个属性 或者通过 D 参数 它会找到它并自动在您的 bean 上设置它 因此 如果您有一个名为 gateway 的 bean 带有属性登录和 setter 则可以在 seam pr
  • 人体全身检测:轮廓而不是矩形

    我必须使用 opencv 实现整个人体的轮廓检测 从脚到头 多种姿势 例如举手等 我设法编译并运行我在这里找到的代码https gist github com yoggy 1470956 https gist github com yogg
  • 按返回类型重载

    我在这里读到了一些关于这个主题的问题 这对我来说似乎仍然令人困惑 我刚刚开始学习C 还没有学习模板或运算符重载等 现在有没有简单的方法来重载 class My public int get int char get int 没有模板或奇怪的
  • 预览版无法在 MobileFirst Platform Foundation Server 7.0 上运行

    在 MobileFirst Server Platform Foundation 7 0 上 预览版在控制台中不起作用 在 Eclipse 开发方面 一切运行良好 The error message is the following 这是日
  • Winform 菜单条和隐藏选项卡

    您好 我正在考虑创建一个选项卡控件 该选项卡页将通过菜单条中的点击进行过滤 For ex 我的菜单条采用表格 1 我的选项卡控件采用表格 2 我的选项卡控件由 7 个选项卡组成 我希望一次只显示 1 个选项卡 例如 如果我单击菜单条中的名称
  • ARM 汇编:存储上的自动递增寄存器

    是否可以使用 STR 自动递增寄存器的基地址 Rn 我仔细阅读了文档 但未能找到明确的答案 主要是因为命令语法同时适用于 LDR 和 STR 理论上它应该适用于两者 但我找不到任何 auto 的示例 在商店上递增 加载正常 我编写了一个小程