0

the function is foo, which is basically counting the number of ones in the valuesarray.

.data
.balign 4
values:
    .word 1
    .word 0
    .word 1 
    .word 2
    .word 1

.balign 4
count: .word 0
.balign 4
return .word 0

.text
.global foo
foo:
    mov r3, #0
    mov r2, #4
    mul r2, r1, r2
    add r2,r0,r2
    mov r4,#1

foo_loop:
    cmp r0,r2
    beq foo_exit
    ldr r1,[r0]
    cmp r1,r4
    beq foo_eq
    add r0,r0,#4
    b foo_loop

foo_eq:
    add r3,r3,#1
    add r0,r0,#4
    b foo_loop

foo_exit:
    mov r0,r3
    bx lr

.global main
main:
    ldr r1, =return
    str lr, [r1]

    ldr r0, =values
    mov r1,#5
    bl foo
    ldr r1, =count
    str r0,[r1]
    ldr lr, =return
    ldr lr,[lr]
    bx lr
Ryan Zhu
  • 543
  • 3
  • 9
  • 20
  • 1
    Which function call convention would that be? – Variable Length Coder Mar 28 '16 at 19:00
  • 2
    The "assembly calling convention", were such a thing defined, would be "whatever the callee code expects", which if you're writing both bits of code simply translates to "whatever you want". Now, if what you wanted was to restrict yourself to the general cross-language ABI, then the question becomes a duplicate of http://stackoverflow.com/q/261419/3156750 – Notlikethat Mar 28 '16 at 20:01
  • @VariableLengthCoder I'm referring to AAPCS convention. – Ryan Zhu Mar 28 '16 at 22:02
  • Well, why don't we start here then, @RyanZhu. What is *your* understanding of that calling convention? – David Hoelzer Mar 29 '16 at 00:12
  • ARM has predicated execution for any instruction you want, so instead of branching, you should just `addeq r3,r3,#1`. IIRC, predication in [thumb-2 mode](https://en.wikipedia.org/wiki/ARM_architecture#Thumb-2) is done with an `IT` (if-then) insn to make the following instruction conditional. Also, put the conditional branch at the bottom of the loop. And accumulate in `r0` in the first place so you don't need a `mov` before you return. – Peter Cordes Mar 29 '16 at 02:27
  • @DavidHoelzer I think this rule could prevent us from some brain teasing work on which register should have which value. – Ryan Zhu Apr 11 '16 at 22:01
  • @PeterCordes I see. Thanks for the answer – Ryan Zhu Apr 11 '16 at 22:02

1 Answers1

1

The only thing I can see which is not correct is that you use register r4 in the function without saving it. Only registers r0-r3 can be used as parameters and scratch registers.

So you should either do this:

.text
.global foo
foo:
    push {r4}
    ...

foo_exit:
    mov r0,r3
    pop {r4}
    bx lr

Or (Saving PC as well on the stack):

.text
.global foo
foo:
    push {r4,pc}
    ...

foo_exit:
    mov r0,r3
    pop {r4,lr}
Dric512
  • 3,525
  • 1
  • 20
  • 27