简体   繁体   English

如何在 ARM 程序集的自定义函数中使用 while 循环(或任何循环)?

[英]How can I use a while loop (or any loop) within a custom function in ARM Assembly?

I am trying to solve a problem where I have a counter that goes from 10 to 50. For each number, I must check if it is a multiple of 8 (if it is, then I store 0xffff in R3), or if it is a multiple of 3 (and I would store 0xbbbb) or if it is a multiple of both (where I store 0xffbb in R3).我试图解决一个问题,我有一个从 10 到 50 的计数器。对于每个数字,我必须检查它是否是 8 的倍数(如果是,那么我将 0xffff 存储在 R3 中),或者如果是3 的倍数(我将存储 0xbbbb)或者如果它是两者的倍数(我将 0xffbb 存储在 R3 中)。

For checking if the number is a multiple of 3, my plan is to subtract 3 from the number until it either reaches 0 or is less than 3. I am struggling to figure out how I can use a loop within a custom function.为了检查数字是否是 3 的倍数,我的计划是从数字中减去 3,直到它达到 0 或小于 3。我正在努力弄清楚如何在自定义函数中使用循环。 Here is my code so far:到目前为止,这是我的代码:

.section    .data
.balign 4
return_start:   .word 0
.balign 4
return_loop:    .word 0
.balign 4
return_8:   .word 0
.balign 4
return_3:   .word 0
.balign 4
return_3loop:   .word 0

.section    .text

.global _start
/* .func   _loop
.func   _multOf8
.func   _multOf3 */

_start:
    LDR R1, addr_return_start
    STR lr, [R1]

    mov r0, #10 /* Start with 10 */
    BL  _loop

    LDR lr, addr_return_start
    LDR lr, [LR]

_loop:
    add R0, #1  /* increment by 1 */
    MOV r3, #0 /* resetting r3 */
    CMP R0, #50 /* check if it is 50, if it is then go to the end */
    BEQ _end

    /* else check if it is a multple of 8 */
    BL  _multOf8
    /* check if it is a multiple of 3 */
    BL  _multOf3

    B   _loop

_multOf8:
    /* save LR */
    LDR R1, addr_return_8
    STR lr, [R1]

    AND r1, r0, #7
    CMP r1, #0
    MOVEQ r3, #0xffff   /* if it is a multiple of 8 */
    /* else return */
    LDR LR, addr_return_8
    LDR LR, [LR]
    BX LR

_multOf3:
    LDR R1, addr_return_3
    STR lr, [R1]

    /* if it is a multiple of 3 */
    /* will need to subtract it continuously? */
    PUSH R0
    BL  _3loop
    POP R0

    LDR LR, addr_return_3
    LDR LR, [lr]
    BX  lr

_3loop:
    LDR R1, addr_return_3loop
    STR lr, [R1]

_end:   B   _end

addr_return_start:  .word return_start

addr_return_loop:   .word return_loop

addr_return_8:  .word return_8

addr_return_3:  .word return_3

addr_return_3loop:  .word return_3loop

As you can see, in the function _multOf3 I am attempting to branch off to _3loop .如您所见,在函数_multOf3我试图分支到_3loop The issue is, that I do not know what to do with LR and how to return from this loop.问题是,我不知道如何处理LR以及如何从此循环返回。 I feel like if I was to store LR, it would continuously be overwritten each time we iterate through the loop.我觉得如果我要存储 LR,每次我们遍历循环时它都会不断地被覆盖。

Any help would be much appreciated!任何帮助将非常感激! Please do note that I am a beginner in ARM Assembly.请注意,我是 ARM 汇编的初学者。

Loops in ARM aren't too complicated. ARM 中的循环并不太复杂。 There's a couple ways to achieve one.有几种方法可以实现。 Generally you'll need to set aside one register as a loop counter.通常,您需要留出一个寄存器作为循环计数器。 The example below is for a decrementing loop.下面的示例用于递减循环。

_loop: /* R2 is the loop counter */

/* do stuff here */

subs R2,R2,#1   /* the S at the end sets the flags accordingly. If the result is zero,
                   the zero flag will be set and BNE will not branch.
BNE _loop
/* if R2 = 0, execution will fall through to here, otherwise it jumps back to the loop's start

An incrementing loop takes an extra step, since you'll need to compare the value of the loop counter to the desired endpoint:递增循环需要一个额外的步骤,因为您需要将循环计数器的值与所需的端点进行比较:

_loop /* R2 is the loop counter */

/* do stuff here */

add R2,R2,#1   /* no need for S at the end, it does us no good here. */
CMP R2,#50     /* 50 was arbitrarily chosen for this example. */
BNE _loop      /* this just checks if they're not equal, for this example it's sufficient but 
               it's better to use BLS for signed numbers or BLO/BCC for unsigned */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM