我正在使用C文件,这是这样的:
#define v2 0x560000a0
int main(void)
{
long int v1;
v1 = ioread32(v2);
return 0;
}
并且我已经提取了这部分以在汇编中编写它:
int main ()
{
extern v1,v2;
v1=ioread32(v2);
return 0;
}
我正在尝试使用armv4的汇编代码在v1中写入v2的值。使用
arm-linux-gnueabi-gcc -S -march=armv4 assembly_file.c
我收到了这段代码:
.arch armv4
.eabi_attribute 27, 3
.fpu vfpv3-d16
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "txind-rsi.c"
.text
.align 2
.global main
.type main, %function
main:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4
ldr r3, .L2
ldr r3, [r3, #0]
mov r0, r3
bl ioread32
mov r2, r0
ldr r3, .L2+4
str r2, [r3, #0]
mov r3, #0
mov r0, r3
sub sp, fp, #4
ldmfd sp!, {fp, lr}
bx lr
.L3:
.align 2
.L2:
.word v1
.word v2
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",%progbits
我使用该代码以这种方式将其放回C文件中:
asm volatile(
"stmfd sp!, {fp, lr}\n"
"add fp, sp, #4\n"
"ldr r3, =v1\n"
"ldr r3, [r3, #0]\n"
"mov r0, r2\n"
"ldr r3, =v2\n"
"str r2, [r3, #0]\n"
"sub sp, fp, #4\n"
"ldmfd sp!, {fp, lr}\n"
"bx lr"
);
代码没有做任何事情。
实际上,它会阻止目标工作。 有人知道为什么吗?
EDITED: 在阅读你的答案后,我有另一个问题: 我如何在寄存器中放置一个常量值? C中的代码是这样的:
#define v2 0x560000a0
int main(void)
{
long int value = 0x0000ffff;
long int v1;
v1 = ioread32(v2);
iowrite32(v2,value);
return 0;
}
我试过这个:
asm volatile("mov r3, #value");
我得到一个汇编信息:“值符号在不同的部分”; 我也试过了
asm volatile("mov r3, #0x0000ffff);
和汇编程序消息是: “修复后的无效常量(ffff)”。阅读完本后:Invalid constant after fixup? 我不知道如何把这个值放到r3中,因为我似乎无法用mov.I使用armv4,而不是armv7。在链接中提出的这个解决方案对我不起作用:
asm volatile("ldr r3, =#0000ffff\n");
答案 0 :(得分:2)
你的代码没有问题,bx lr是终止main的正确方法,没有问题。由于您正在访问的地址,您的代码很可能会崩溃,它可能不是您可以访问的地址...
#define v2 0x560000a0
int main(void)
{
long int v1;
v1 = ioread32(v2);
return 0;
}
如果优化C编译步骤,您可以看到更简洁的版本
00000000 <main>:
0: e92d4008 push {r3, lr}
4: e59f0008 ldr r0, [pc, #8] ; 14 <main+0x14>
8: ebfffffe bl 0 <ioread32>
c: e3a00000 mov r0, #0
10: e8bd8008 pop {r3, pc}
14: 560000a0 strpl r0, [r0], -r0, lsr #1
这在asm中并不难实现。
.globl main
main:
push {r3,lr}
ldr r0,=0x560000A0
bl ioread32
mov r0,#0
pop {r3,pc}
组装和拆卸
00000000 <main>:
0: e92d4008 push {r3, lr}
4: e59f0008 ldr r0, [pc, #8] ; 14 <main+0x14>
8: ebfffffe bl 0 <ioread32>
c: e3a00000 mov r0, #0
10: e8bd8008 pop {r3, pc}
14: 560000a0 strpl r0, [r0], -r0, lsr #1
您已将代码简化为v1变为死代码,但函数调用无法优化,因此返回将被丢弃。
如果你不使用main但是创建一个单独的函数返回
#define v2 0x560000a0
long int fun(void)
{
long int v1;
v1 = ioread32(v2);
return v1;
}
...该死...尾部优化:
00000000 <fun>:
0: e59f0000 ldr r0, [pc] ; 8 <fun+0x8>
4: eafffffe b 0 <ioread32>
8: 560000a0 strpl r0, [r0], -r0, lsr #1
好吧,好吧。您走在正确的道路上,看看C编译器生成了什么,然后模仿或修改它。我怀疑这是你的ioread是问题,而不是外部结构(你为什么用32位读取做64位的事情,也许这就是问题很长,它很可能会被实现为64位)。 / p>
答案 1 :(得分:1)
最后的bx lr
会尝试从当前函数返回。你可能不希望这样。我想这也是崩溃的原因,因为你不要让编译器撤消它在函数序言中所做的任何设置。
此外,在您的asm块中,您不使用任何本地,因此您不需要调整堆栈指针,也不需要新的堆栈帧。由于您已将值加载到mov r0, r2
,r3
也会被破坏。如果您只是直接加载到您想要的任何寄存器中,您可以删除mov
。此外,在gcc内联asm中,您应该告诉编译器您修改了哪些寄存器。不这样做也会导致崩溃,因为您可能会覆盖编译器所依赖的值。
不确定在装配中这样做有什么意义。如果你坚持这一点,以下应该会有所改善:
asm volatile(
"ldr r3, =v1\n"
"ldr r2, [r3, #0]\n"
"ldr r3, =v2\n"
"str r2, [r3, #0]\n" ::: "r2", "r3"
);