0

I am trying to populate my array a in the ARM program below, the program ran with no issues when populating it with the i value, but I am now trying to populate indexes with user input. My implemented _scanf has no issues either as I used it in many programs before (called it in many other programs), but in this program, it is suppose to stop at 10 but it doesn't. It keeps going and I have no clue where the problem is.

.global main
.func main

main:

    MOV R3, #0              @ initialze index variable
    BL writeloop            @ call write function
    BL readloop             @call read function (prints a)

writeloop:


    CMP R3, #10            @ check to see if we are done iterating
    BEQ writedone           @ exit loop if done
    LDR R1, =a              @ get address of a
    LSL R2, R3, #2          @ multiply index*4 to get array offset
    ADD R2, R1, R2          @ R2 now has the element address
    BL _scanf
    MOV R4,R0
    STR R4, [R2]            @ write input to a[i]
    ADD R3, R3, #1          @ increment index
    B   writeloop           @ branch to next loop iteration
writedone:
    MOV R3, #0              @ initialze index variable
readloop:
    CMP R3, #10            @ check to see if we are done iterating
    BEQ readdone            @ exit loop if done
    LDR R1, =a              @ get address of a
    LSL R2, R3, #2          @ multiply index*4 to get array offset
    ADD R2, R1, R2          @ R2 now has the element address
    LDR R1, [R2]            @ read the array at address 
    PUSH {R3}               @ backup register before printf
    PUSH {R1}               @ backup register before printf
    PUSH {R2}               @ backup register before printf
    MOV R2, R1              @ move array value to R2 for printf
    MOV R1, R3              @ move array index to R1 for printf
    BL  _printf             @ branch to print procedure with return
    POP {R2}                @ restore register
    POP {R1}                @ restore register
    POP {R3}                @ restore register
    ADD R3, R3, #1          @ increment index
    B   readloop            @ branch to next loop iteration
readdone:
    MOV R3,#0               @reset counter (i)


 _scanf:
    PUSH {LR}               @ store the return address
    PUSH {R1}               @ backup regsiter value
    LDR R0, =format_str     @ R0 contains address of format string
    SUB SP, SP, #4          @ make room on stack
    MOV R1, SP              @ move SP to R1 to store entry on stack
    BL scanf                @ call scanf
    LDR R0, [SP]            @ load value at SP into R0
    ADD SP, SP, #4          @ remove value from stack
    POP {R1}                @ restore register value
    POP {PC}                @ restore the stack pointer and return   




_exit:  
    MOV R7, #4              @ write syscall, 4
    MOV R0, #1              @ output stream to monitor, 1
    MOV R2, #21             @ print string length
    LDR R1, =exit_str       @ string at label exit_str:
    SWI 0                   @ execute syscall
    MOV R7, #1              @ terminate syscall, 1
    SWI 0                   @ execute syscall

_printf:
    PUSH {LR}               @ store the return address
    LDR R0, =printf_str     @ R0 contains formatted string address
    BL printf               @ call printf
    POP {PC}                @ restore the stack pointer and return



.data

format_str:     .asciz      "%d"

.balign 4
a:              .skip       40
printf_str:     .asciz      "a[%d] = %d\n"
exit_str:       .ascii      "Terminating program.\n"
Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
aero
  • 372
  • 1
  • 4
  • 18
  • `R3` is caller-saved register so `BL scanf` will destroy its value. PS: learn to use a debugger. – Jester May 07 '16 at 19:11
  • _scanf return value should be stored in R0, what does R3 have to do with it? – aero May 07 '16 at 19:17
  • You use `R3` as counter, but since it's caller saved according to the ABI, the `BL scanf` may change it as it likes. – Jester May 07 '16 at 19:27
  • So, should I use the R0 as a counter, what about _scanf return value? – aero May 07 '16 at 19:48
  • 2
    Possible duplicate of [ARM to C calling convention, registers to save](http://stackoverflow.com/questions/261419/arm-to-c-calling-convention-registers-to-save) – Notlikethat May 07 '16 at 19:52

1 Answers1

0
.global main
.func main

main:

    MOV R3, #0              @ initialze index variable
    BL writeloop            @ call write function
    BL readloop             @call read function (prints a)

writeloop:


    CMP R3, #10            @ check to see if we are done iterating
    BEQ writedone           @ exit loop if done
    LDR R1, =a              @ get address of a
    LSL R2, R3, #2          @ multiply index*4 to get array offset
    ADD R2, R1, R2          @ R2 now has the element address
    BL _scanf
    MOV R4,R0
    STR R4, [R2]            @ write input to a[i]
    ADD R3, R3, #1          @ increment index
    B   writeloop           @ branch to next loop iteration
writedone:
    MOV R3, #0              @ initialze index variable
readloop:
    CMP R3, #10            @ check to see if we are done iterating
    BEQ readdone            @ exit loop if done
    LDR R1, =a              @ get address of a
    LSL R2, R3, #2          @ multiply index*4 to get array offset
    ADD R2, R1, R2          @ R2 now has the element address
    LDR R1, [R2]            @ read the array at address 
    PUSH {R3}               @ backup register before printf
    PUSH {R1}               @ backup register before printf
    PUSH {R2}               @ backup register before printf
    MOV R2, R1              @ move array value to R2 for printf
    MOV R1, R3              @ move array index to R1 for printf
    BL  _printf             @ branch to print procedure with return
    POP {R2}                @ restore register
    POP {R1}                @ restore register
    POP {R3}                @ restore register
    ADD R3, R3, #1          @ increment index
    B   readloop            @ branch to next loop iteration
readdone:
    MOV R3,#0               @reset counter (i)


_exit:  
    MOV R7, #4              @ write syscall, 4
    MOV R0, #1              @ output stream to monitor, 1
    MOV R2, #21             @ print string length
    LDR R1, =exit_str       @ string at label exit_str:
    SWI 0                   @ execute syscall
    MOV R7, #1              @ terminate syscall, 1
    SWI 0                   @ execute syscall

@ ---- Moved below _exit, added R2 and R3 to PUSH and POP
 _scanf:
    PUSH {LR}               @ store the return address
    PUSH {R1, R2, R3}               @ backup regsiter value
    LDR R0, =format_str     @ R0 contains address of format string
    SUB SP, SP, #4          @ make room on stack
    MOV R1, SP              @ move SP to R1 to store entry on stack
    BL scanf                @ call scanf
    LDR R0, [SP]            @ load value at SP into R0
    ADD SP, SP, #4          @ remove value from stack
    POP {R1, R2, R3}                @ restore register value
    POP {PC}                @ restore the stack pointer and return   

_printf:
    PUSH {LR}               @ store the return address
    LDR R0, =printf_str     @ R0 contains formatted string address
    BL printf               @ call printf
    POP {PC}                @ restore the stack pointer and return



.data

format_str:     .asciz      "%d"

.balign 4
a:              .skip       40
printf_str:     .asciz      "a[%d] = %d\n"
exit_str:       .ascii      "Terminating program.\n"

You might want to review http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf Chapter 5, page 14.

bstipe
  • 252
  • 2
  • 6