jjzjj

c++ - 有人可以帮助我了解 stmdb、ldmia 以及如何用 arm 汇编语言实现此 C++ 代码吗?

coder 2024-02-07 原文

所以我有这段代码,其中 N 是两个数组的大小。

int i;

for (i = 0; i < N; i++)
{
    if (listA[i] < listB[i])
    {
        listA[i] = listB[i];
    }
}

我正在尝试将其实现为 ARM 汇编子例程,但我完全不知道如何处理数组。到目前为止我有这个:

sort1:
    stmdb    sp!, {v1-v5, lr}
    ldmia    sp!, {v1-v5, pc}

我假设我必须使用 cmp 来比较这些值,但我什至不确定要使用什么寄存器。有人有任何指导吗?

编辑:

好的,我现在有了这段代码:

sort1:
    stmdb    sp!, {v1-v5, lr}     @ Copy registers to stack
    ldr      v1, [a1], #0         @ Load a1
    str      v1, [a2], #0         @ Copy elements of a1 to a2 
    ldmia    sp!, {v1-v5, pc}     @ Copy stack back into registers

这复制了一个 10 元素数组的前四个元素,所以我假设如果我将“#0”更改为“#4”,它会导致接下来的四个元素发生变化,但事实并非如此。为什么?

最佳答案

首先,正如您所展示的,加载/存储多条指令主要用于堆栈操作(尽管它们也可以生成高效的 memcpy)。简而言之,它们按顺序加载/存储指定的寄存器,从/到一个连续的内存块,从base addressbase address + (number of registers * 4) .

在给出的示例中,stmdb sp!, {v1-v5, lr} 以“Decrement Before”寻址模式1 存储 6 个寄存器,因此有效基地址是 sp-24 - 它会将 v1 的内容存储在 sp-24v2sp-20,... lr at sp-4。由于存在用于基址寄存器写回的 ! 语法,因此它将从 sp 中减去 24,使其指向 v1 的存储值。 ldmia 完全相反 - “Increment After”表示有效基地址为 sp,因此它将从 sp 加载寄存器直到sp+20,然后将 24 添加到 sp。请注意,它将堆叠的 lr 值直接加载到 pc - 这样您就可以在一条指令中恢复寄存器并执行函数返回。


对于常规的加载/存储指令,它们有 3 种寻址模式 - 偏移、预索引和后索引。 ldr v1, [a1], #0是后置索引的,意思是“从a1中的地址加载v1,然后将0加到a1”,因此将 #0 更改为 #4 不会影响使用的地址,只会影响写回的值之后到基址寄存器。如果您已经实现了循环,效果就会变得清晰可见。

考虑一些示例 C 表达式如何映射到这些寻址模式可能会有所帮助:

int a;       // r0
int *b;      // r1

a = b[1];    // ldr r0, [r1, #4]   (offset)
a = *(b+1);  // similarly

a = *(++b);  // ldr r0, [r1, #4]!  (pre-indexed)

a = *(b++);  // ldr r0, [r1], #4   (post-indexed)

请记住,偏移值也可以是寄存器而不是立即数,因此有几种可能的方法来实现与给定的循环类似的循环。

对于权威引用,我建议阅读 ARM Architecture Reference Manual 的说明部分,或者为了不那么详尽但更容易理解的介绍,Cortex-A Series Programmer's Guide .


[1] 这意味着递减堆栈 - 相应的“递减之后”和“递增之前”寻址模式存在用于运行递增堆栈。

关于c++ - 有人可以帮助我了解 stmdb、ldmia 以及如何用 arm 汇编语言实现此 C++ 代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23045702/

有关c++ - 有人可以帮助我了解 stmdb、ldmia 以及如何用 arm 汇编语言实现此 C++ 代码吗?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  6. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  7. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  8. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  9. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  10. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

随机推荐