0

I tried translate the following C code into arm language

int main(int argc,char **argv){

    for(int i=strlen(argv[1])-1;i!=-1;i--)printf("%c",argv[1][i]);

}

The C code is reverse the string from argv[1]

$ g++ -o reverse reverse.c

$ ./reverse abcd

$ dcba

I know the string argv[1] is store in r1+4 and argc store in r0

but I don't know what's the end address of the string argv[1],I found a post which writes that r0 store the length of r1,so I write my code base on this post, here is my arm code

 @@@@ input : hi 
 @@@@ expected output : ih
 @@@@ if "hi" is a string named a-> string aaa="hi"
 @@@@ so r3=aaa[0],and the length of aaa is r2

    .text   
    .align 2
    .global main
    .extern printf
main:
    stmfd sp!, {r0,r1,r2,r3,fp,lr}
    ldr r3,[r1,#4] ; r3 = a pointer point to argv[1]
    mov r2,r0
    sub r2,r2,#4  ;minus the last character (terminated character) 
    b LOOP
    ldmfd sp!, {r0,r1,r2,r3,fp,lr}
    bx lr

LOOP:
    ldr r0,=string
    cmp r2,r3 
    subne r2,r2,#4 ; if r2 != r3 , r2=r2-4 (address step forward) 
    bl printf ; print one character 
    bne LOOP

string:
    .asciz "%c"

this arm code is run in CodeSourcery

$ arm-none-eabi-gcc j.s -T generic-hosted.ld

$ arm-none-eabi-run a.out "hi"

$ (nothing print,what I expected output : ih)

how can I fixed my code? this question disturb me for 3 days

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
achicn3
  • 93
  • 2
  • 9
  • This is not really a question about C. – jxh Nov 07 '17 at 18:57
  • why use assembler, when are used inefficient functions, for example `printf`? – Jacek Cz Nov 07 '17 at 18:57
  • If this is C code, why do you compile it with `g++`, a compiler for C++? – fuz Nov 07 '17 at 19:01
  • 1
    Single-step your code with a debugger. The most obvious problem is that when `bne` falls through, you fall off the end of your code. Also, `printf` (and any other ABI-compliant function) can/will clobber `r0-r3`, so your loop should use a call-preserved register. (Similarly, you don't need to save/restore r0..r3 with push/pop around main.) – Peter Cordes Nov 07 '17 at 19:05
  • See https://stackoverflow.com/questions/39503997/how-to-run-a-single-line-of-assembly-then-see-r1-and-condition-flags for using qemu + gdb to debug an ARM binary on an x86 Linux desktop. (But I didn't try with libc, just a bare environment). – Peter Cordes Nov 07 '17 at 19:10
  • 1
    Hint, it would be *much* more efficient to reverse the string in memory and then make one `puts` call (or a `write` system call.) – Peter Cordes Nov 07 '17 at 19:10
  • 1
    if you already have C++ version, you can also check what gcc does produce.. try -O1 or -O2 to get a bit cleaned up/optimized code, but not too advanced one (like unrolled loops/etc). Trying to understand/modify that may give you another insight and ideas. – Ped7g Nov 07 '17 at 21:41
  • oh,it's gcc @fuz – achicn3 Nov 08 '17 at 04:23
  • @PeterCordes what is call-preserved register? Do you mean I have use such as r4,r5,r6... to store r0-r3? I will use qemu+gdb to debug my arm later – achicn3 Nov 08 '17 at 04:37
  • google caller-saved vs. callee-saved and calling conventions. I prefer the terms call-preserved vs. call-clobbered because they describe it better. – Peter Cordes Nov 08 '17 at 04:48
  • 1
    @achicn3 Yes, but `g++` is the GNU C++ compiler. Type `gcc` to get the GNU C compiler instead. – fuz Nov 08 '17 at 10:48

1 Answers1

1

This code work perfectly.

area reverseString,code
CR EQU 0x0D
 entry
 ldr r0,=data
 ldr r2,=0x40000000
 ldr r3,=0x40000020
 mov r4,#00

up ldrb r5,[r0],#1
 cmp r5,#CR
 strb r5,[r2],#1
 add r4,r4,#1
 BNE up
 sub r4,r4,#1
 sub r2,r2,#2
 BNE down

down ldrb r6,[r2]
 strb r6,[r3],#1
 sub r2,r2,#1
 subs r4,r4,#1
 BNE down


stop b stop
data dcb "Vidya",CR
 end
Vidya
  • 382
  • 1
  • 6
  • 17
  • What are these magic constant addresses 0x40000000 and 0x40000020 for? How do you know that space is going to be free for use as a scratch buffer after linking with the GNU toolchain, including libc, and why don't you just label the start and end of a buffer in the `.bss` like a normal person? – Peter Cordes Dec 14 '19 at 05:44