【发布时间】: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