【问题标题】:reverse string in arm手臂反弦
【发布时间】:2017-11-07 18:53:18
【问题描述】:

我尝试将以下 C 代码翻译成 arm 语言

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

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

}

C 代码是从 argv[1] 反转字符串

$ g++ -o reverse reverse.c

$ ./reverse abcd

$ dcba

我知道字符串 argv[1] 存储在 r1+4 和 argc 存储在 r0

但是我不知道字符串 argv[1] 的结束地址是什么,我找到了一个帖子说 r0 存储 r1 的长度,所以我根据这篇帖子编写了我的代码,这是我的 arm 代码

 @@@@ 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"

这个 arm 代码在 CodeSourcery 中运行

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

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

$(没有打印,我期望的输出:ih)

如何修复我的代码?这个问题困扰了我3天

【问题讨论】:

  • 这不是一个关于 C 的问题。
  • 使用调试器单步执行您的代码。最明显的问题是当bne 失败时,你会从代码的末尾掉下来。此外,printf(和任何其他符合 ABI 的函数)可以/将破坏r0-r3,因此您的循环应该使用保留调用的寄存器。 (同样,您不需要在 main 周围使用 push/pop 来保存/恢复 r0..r3。)
  • 提示,在内存中反转字符串然后进行一次puts 调用(或write 系统调用)会更有效。
  • 如果您已经有 C++ 版本,您还可以检查 gcc 生成的内容。尝试使用 -O1 或 -O2 来清理/优化代码,但不要太高级(如展开循环/ETC)。尝试理解/修改可能会给您带来另一种见解和想法。
  • @achicn3 是的,但g++ 是 GNU C++ 编译器。键入 gcc 以获取 GNU C 编译器。

标签: c assembly arm calling-convention


【解决方案1】:

这段代码完美运行。

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

【讨论】:

  • 这些神奇的常量地址 0x40000000 和 0x40000020 是干什么用的?你怎么知道在与 GNU 工具链(包括 libc)链接后,空间将被免费用作暂存缓冲区,以及为什么不像正常一样在 .bss 中标记缓冲区的开始和结束人?
猜你喜欢
  • 1970-01-01
  • 2019-02-12
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 2021-08-15
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多