首页 > 解决方案 > 不明白如何完成这个 ARM 汇编代码来做 5 个数字的总和和余数的平均值

问题描述

我正在尝试学习 ARM 汇编,我发现了这个练习并试图解决它。

我做了这段代码,但我真的不知道如何修复和继续它,因为我知道有些部分丢失了。我首先尝试做总和部分,但不明白如何做前 5 个数字和其他数字的平均值。

这是练习:

给定 N=21 个正整数的向量 V[],存储从内存位置 0x100 开始的变量。

- 计算前 5 个数字的总和,然后计算余数的平均值。

- 识别获得的两个值中的较大者和较小者,并将第一个存储在位置 0x200 中,第二个存储在位置 0x500 中。

这是我试图完成和修复的代码:

ENTRY
    MOV R0, #21         ; Counter for array
    LDR R1, =array      ; Register for array
loop    LDR R2, [R1], #20   ; Loading value from array and updating(increment) the address
    ADD R3,R3,R2        ; Sum is stored in R3 register
    SUB R0,R0,#1        ; Decrementing counter value
    CMP R0,#00          ; Checking counter value
    BNE loop
    END 

编辑:我解决了一些问题,这就是结果,而不是最终结果,因为我必须检查它是否在我的机器上正常工作。

            MOV R0, #21                 ; Counter array
            LDR R1, =array, #0x100      ; Array at 0x100
loopsum   LDR R2, [R1], #20           ; Loading value from array and updating(increment) the address
            ADD R3,R3,R2                ; Put sum in R3
            SUB R0,R0,#1                ; decrease counter
            CMP R0,#16                  ; check if first 5
            Bne loopsum

loopmean   LDR R2, [R1], #16           ; Loading value from array and updating(increment) the address
            ADD R4,R4,R2                ; put sum in R4
            SUB R0,R0,#1                ; decrease counter
            CMP R0,#0                   ; check if ended
            Bne loopmean

            MOV R4, R4, ASR 16          ;divide by 16
            MOV R5, #0x200              ;address for max
            MOV R6, #0x500              ;address for min

            CMP R3, R4                  ;R3 > R4 ?
            MOVgt R5, R3                ;if yes puts R3 in R5
            MOVle R6, R4                ;R4 in R6

            CMP R4, R3                  ;R4 > R3 ?
            MOVgt R5, R4                ;if yes puts R4 in R5
            Movle R6, R3                ;R3 in R6

            END

标签: assemblyarm

解决方案


我了解您的教授要教什么,但他应该先教AAPCS,以及如何使例程以适当的独立功能 IMO。

下面是三个函数:

  • void myFunc(uint32_t *pArray, uint32_t *pLesser, uint32_t *pGreater);
  • void myFunc_mf(uint32_t *pArray, uint32_t *pLesser, uint32_t *pGreater);
  • void myFunc_bfmf(uint32_t *pArray, uint32_t *pLesser, uint32_t *pGreater);

正如参数名称所暗示的那样,您应该分别使用参数 0x100、0x500 和 0x200 来调用它们,以满足您教授的要求

第一个(myFunc)可能是您的教授所期望的:运行循环。

第二个和第三个通过展示一个真正的汇编程序员如何在 ARM 整数内核或 NEON 上处理这个问题,向这个有点愚蠢和不切实际的分配展示了中指(和一个大的他妈的一个)。

请注意,霓虹灯版本是最短的。

    .syntax unified
    .arm
    .arch   armv7-a
    .fpu    neon
    .global myFunc, myFunc_mf, myFunc_bfmf
    .text


.balign 64
.func
// void myFunc(uint32_t *pArray, uint32_t *pLesser, uint32_t *pGreater);

pArray  .req    r0
pLesser .req    r1
pGreater    .req    r2
counter .req    r3
sum     .req    r12
mean1   .req    r6
mean2   .req    r7
lesser  .req    pArray
greater .req    mean2


myFunc:
    push    {r4-r7}
    mov     counter, #5
    mov     sum, #0
    mov     mean1, #0
    mov     mean2, #0
    b       1f

.balign 64
1:
    ldr     r4, [pArray], #4
    subs    counter, counter, #1
    add     sum, sum, r4
    bne     1b

/////////////////////////////////////////////////////

    mov     counter, #16
    b       1f

.balign 64
1:
    ldrd    r4, r5, [pArray], #8
    subs    counter, counter, #2
    add     mean1, mean1, r4
    add     mean2, mean2, r5
    bne     1b

    add     mean1, mean2, mean1
    lsr     mean1, mean1, #4

/////////////////////////////////////////////////////

    cmp     mean1, sum
    mov greater, mean1
    mov lesser, sum
    movlo   greater, sum
    movlo   lesser, mean1

    str     greater, [pGreater]
    str     lesser, [pLesser]

    pop     {r4-r7}
    bx      lr
.endfunc

.balign 64
.func
myFunc_mf:
    push    {r4-r11}

    ldmia   pArray!, {r4-r8}
    add     r4, r5, r4
    add     r6, r7, r6
    add     r4, r4, r8
    add     r3, r4, r6

    ldmia   pArray!, {r4-r11}
    add     r4, r5, r4
    add     r6, r7, r6
    add     r8, r9, r8
    add     r10, r11, r10
    add     r4, r6, r4
    add     r8, r10, r8
    add     r12, r8, r4

    ldmia   pArray, {r4-r11}
    add     r4, r5, r4
    add     r6, r7, r6
    add     r8, r9, r8
    add     r10, r11, r10
    add     r4, r6, r4
    add     r8, r10, r8

    add     r12, r4, r12
    add     r12, r12, r8
    lsr     r12, r12, #4

    cmp     r12, r3
    mov r4, r12
    mov r5, r3
    movlo   r4, r3
    movlo   r5, r12

    str     r4, [pGreater]
    str     r5, [pLesser]

    pop     {r4-r11}
    bx      lr
.endfunc

.balign 64
.func
myFunc_bfmf:
    vmov.i32    d2, #0
    vld1.32     {q0}, [pArray]!
    vld1.32     {d2[0]}, [pArray]!
    vld1.32     {q2, q3}, [pArray]!
    vld1.32     {q8, q9}, [pArray]

    vpaddl.u32  q0, q0
        vpaddl.u32  q2, q2
        vpaddl.u32  q3, q3
    vpadal.u32  d0, d2
        vpadal.u32  q2, q8
        vpadal.u32  q3, q9
    vadd.u64    d0, d0, d1
        vadd.u64    q2, q3, q2
        vadd.u64    d4, d5, d4
        vshr.u64    d1, d4, #4

    vmax.u32    d2, d1, d0
    vmin.u32    d3, d1, d0

    vst1.32     {d2[0]}, [pGreater]
    vst1.32     {d3[0]}, [pLesser]

    bx      lr
.endfunc
.end

推荐阅读