首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分拣臂组件

分拣臂组件
EN

Stack Overflow用户
提问于 2016-10-31 20:09:51
回答 1查看 3.8K关注 0票数 0

我是新手。我很难理解记忆手臂记忆图。

我找到了简单排序算法的例子。

代码语言:javascript
复制
    AREA ARM, CODE, READONLY

    CODE32
    PRESERVE8

    EXPORT __sortc
    ; r0 = &arr[0]
    ; r1 = length 

__sortc
    stmfd sp!, {r2-r9, lr}

    mov r4, r1                  ; inner loop counter
    mov r3, r4
    sub r1, r1, #1
    mov r9, r1                  ; outer loop counter                        

outer_loop
    mov r5, r0
    mov r4, r3

inner_loop
    ldr r6, [r5], #4
    ldr r7, [r5]
    cmp r7, r6

    ; swap without swp
    strls r6, [r5]
    strls r7, [r5, #-4] 

    subs r4, r4, #1
    bne inner_loop

    subs r9, r9, #1  
    bne outer_loop  

    ldmfd sp!, {r2-r9, pc}^

    END

这个程序集应该从C代码以这种方式调用

代码语言:javascript
复制
#define MAX_ELEMENTS    10

extern void __sortc(int *, int);

int main()
{
        int arr[MAX_ELEMENTS] = {5, 4, 1, 3, 2, 12, 55, 64, 77, 10};

    __sortc(arr, MAX_ELEMENTS);

    return 0;
}

据我所知,这段代码在堆栈上创建整数数组,并调用在程序集中实现的_sortc函数。该函数从堆栈中获取这些值,并对它们进行排序,并将其放回堆栈中。我说得对吗?

我想知道如何仅使用程序集来实现这个示例。

例如,定义整数数组

DCD 3, 7, 2, 8, 5, 7, 2, 6

BTW,其中DCD声明的变量存储在内存?中。

如何对以这种方式声明的值进行操作?请解释如何使用程序集来实现这个功能,它没有任何C代码,甚至没有堆栈,只是使用原始数据。

我是为ARM7TDMI架构写作的

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-31 20:49:59

AREA ARM, CODE, READONLY --这标志着源代码中代码部分的开始。

使用类似的AREA myData, DATA, READWRITE,您可以从可以定义数据(如data1 DCD 1,2,3 )的部分开始,这将编译为三个单词,值1、2、3为连续字节,标签data1指向第一个单词的第一个字节。(一些面积,面积文档来自谷歌)。

加载可执行文件后,这些文件在物理内存中的位置取决于可执行文件的链接方式(链接器使用的脚本文件帮助他决定放置哪个区域,以及如何为可执行加载程序完成的动态重定位创建符号表,通过编辑链接器脚本,您可以调整代码和数据所在的位置,但通常不需要这样做)。

此外,链接器脚本和汇编程序指令可能会影响可用堆栈的大小,以及它在物理内存中的映射位置。

因此,对于您的特定平台: google用于web上的内存映射并检查链接器脚本(首先,只需使用链接器选项生成.map文件,以查看代码和数据指向何处)。

因此,您可以在某个数据区域声明该数组,然后使用它将符号data1加载到寄存器("load address of data1")中,并使用它从该地址获取内存内容。

或者,您可以首先将所有数字放入堆栈(您的可执行文件的OS加载程序可能将其设置为合理的数字),然后使用堆栈指针在代码中操作,以访问其中的数字。

您甚至可以将一些值DCDCODE区域,因此这些单词将结束在内存中的指令之间,这些指令被可执行加载程序映射为只读。您可以读取这些数据,但是写入这些数据可能会导致崩溃。当然,您不应该意外地将它们作为指令执行(忘记在DCD之前放置一些ret/跳转指令)。

无栈

嗯,这是一个棘手的问题,你必须小心不要使用任何调用/等等,并禁用中断,等等。基本上,任何需要堆栈的东西。

当人们编写引导程序时,通常会在前几条指令中尽快设置一些临时堆栈,这样他们就可以在正确设置整个环境或加载OS之前使用基本的堆栈功能。该临时堆栈的空间通常在代码中/之后的某个位置保留,或者根据重置后的机器状态保留未使用的内存空间。

如果你是金属,没有操作系统,通常所有的内存在重置后都是可写的,所以你可以随意混合代码和数据(只是跳过数据,而不是偶然地执行它们),而不需要使用区域定义。

但是,您应该考虑一下,是在某些OS的用户空间中创建应用程序(因此您有定义良好的堆栈和数据区域,并且您可以为您的方便使用它们),或者您正在创建引导加载程序代码,这些代码必须自行设置(更困难,因此我建议您首先进入某些OS的用户域,使用带有clib初始化的C包装器通常也很方便,这样您就可以从ASM调用诸如printf之类的东西,以获得方便的输出)。

如何对以这种方式声明的值进行操作?

在机器代码中,声明值的方式并不重要。重要的是,如果您有内存的地址,如果您知道结构,数据是如何存储在那里的。然后你可以用任何你想要的方式和他们一起工作,使用你想要的任何指令。所以ASM示例的主体不会改变,如果您在asm中分配数据,您将把指针作为参数传递给它,就像C一样。

编辑:有些示例在没有测试的情况下盲目地完成,可能需要进一步修改语法才能适用于OP (或者甚至有一些bug,它根本不起作用,如果有的话,请在注释中告诉我):

代码语言:javascript
复制
    AREA myData, DATA, READWRITE

SortArray
    DCD     5, 4, 1, 3, 2, 12, 55, 64, 77, 10
SortArrayEnd

    AREA ARM, CODE, READONLY

    CODE32
    PRESERVE8

    EXPORT __sortasmarray

__sortasmarray
    ; if "add r0, pc, #SortArray" fails (code too far in memory from array)
    ; then this looks like some heavy weight way of loading any address
    ; ldr   r0, =SortArray
    ; ldr   r1, =SortArrayEnd

    add   r0, pc, #SortArray    ; address of array
    ; calculate array size from address of end
    ; (as I couldn't find now example of thing like "equ $-SortArray")
    add   r1, pc, #SortArrayEnd
    sub   r1, r1, r0
    mov   r1, r1, lsr #2
    ; do a direct jump instead of "bl", so __sortc returning
    ; to lr will actually return to called of this
    b     __sortc

    ; ... rest of your __sortc assembly without change    

您可以从C代码调用它,如下所示:

代码语言:javascript
复制
extern void __sortasmarray();

int main()
{
    __sortasmarray();
    return 0;
}

我使用这个介绍ARM汇编语言来刷新我的ARM asm内存,但我仍然担心这可能不能正常工作。

如您所见,我没有在中更改任何内容。因为访问堆栈内存或"dcd“内存没有区别,所以它是同一台计算机内存。一旦您有了特定单词的地址,您就可以使用该地址获得ldr/str它的值。__sortc接收数组中第一个字的地址,以便在这两种情况下进行排序,从这两种情况下它只是内存,没有任何上下文--在源中如何定义该内存、如何分配、初始化等等。只要它是可写的,对于__sortc来说也是可以的。

因此,我唯一与"dcd“相关的东西是加载数组地址,快速搜索ARM示例表明它可以通过几种方式完成,这种add rX, pc, #label方法是最优的,但是只在+-4k范围内工作吗?也有伪指令ADR rX, #label做同样的事情,或者在发生范围问题时切换到其他的?对于任何范围,它看起来都像是使用了ldr rX, = label表单,尽管我不确定它是伪指令还是它是如何工作的,请检查一些教程并反汇编机器代码以查看它是如何编译的。

这取决于您学习所有ARM程序集的特性和如何加载数组的地址,我现在不需要ARM ASM,所以我没有深入这些细节。

应该有一些equ方法来定义数组的长度,而不是用end地址的代码来计算它,但是我找不到任何例子,我也不会阅读完整的汇编程序文档来了解它的所有指令(在gas中,我认为ArrayLength equ ((.-SortArray)/4)会工作)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40349817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档