使用 gcc 和宏将 ARMv7-M 汇编代码内联到 c
inline ARMv7-M assembly code into c using gcc and macros
我的代码运行良好:
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word 0x401C4000 \n"
:: "i" (1<<17), "i" (16)
);
}
但是为了声明 .ADDRESS
我使用了幻数 0x401C4000。我实际上有一个宏。
例如:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)ADDR_BASE)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR)
);
}
那不成立。
在这种情况下如何使用宏?
请参阅下面的编辑。我只是将第一个解决方案作为您不应该做的事情的示例。
我发现了这个 ,其中针对我的相同问题提供了解决方案,但它涉及 x86。
无论如何我都想尝试一下,而且有效。
然后使用%c2
代替%2
,如下所示:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %c2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR): "r2", "r3", "memory"
);
}
编辑
通过查看生成的代码,我上面建议的解决方案可能不起作用:
20 function:
21 @ Function supports interworking.
22 @ args = 0, pretend = 0, frame = 0
23 @ frame_needed = 1, uses_anonymous_args = 0
24 @ link register save eliminated.
25 0000 04B02DE5 str fp, [sp, #-4]!
26 0004 00B08DE2 add fp, sp, #0
27 .syntax divided
28 @ 6 "test.c" 1
29 0008 04309FE5 ldr r3, .ADDRESS
30 000c 0228A0E3 mov r2, #131072
31 0010 102083E5 str r2, [r3, #16]
32 0014 00401C40 .ADDRESS: .word 1075593216
33
34 @ 0 "" 2
35 .arm
36 .syntax unified
37 0018 0000A0E1 nop
38 001c 00D08BE2 add sp, fp, #0
39 @ sp needed
40 0020 04B09DE4 ldr fp, [sp], #4
41 0024 1EFF2FE1 bx lr
可以看到第32行已经发出了符号.ADDRESS
,但是它被代码包围了,没有指示跳过它。我相信它可以像指令一样被尝试执行。
也许彼得建议的更好的解决方案是
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
"str %0, [%2, %1]"
:: "r" (1<<17), "i" (16), "r" (ADDR) : "memory"
);
}
我的代码运行良好:
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word 0x401C4000 \n"
:: "i" (1<<17), "i" (16)
);
}
但是为了声明 .ADDRESS
我使用了幻数 0x401C4000。我实际上有一个宏。
例如:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)ADDR_BASE)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR)
);
}
那不成立。
在这种情况下如何使用宏?
请参阅下面的编辑。我只是将第一个解决方案作为您不应该做的事情的示例。
我发现了这个
然后使用%c2
代替%2
,如下所示:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %c2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR): "r2", "r3", "memory"
);
}
编辑
通过查看生成的代码,我上面建议的解决方案可能不起作用:
20 function:
21 @ Function supports interworking.
22 @ args = 0, pretend = 0, frame = 0
23 @ frame_needed = 1, uses_anonymous_args = 0
24 @ link register save eliminated.
25 0000 04B02DE5 str fp, [sp, #-4]!
26 0004 00B08DE2 add fp, sp, #0
27 .syntax divided
28 @ 6 "test.c" 1
29 0008 04309FE5 ldr r3, .ADDRESS
30 000c 0228A0E3 mov r2, #131072
31 0010 102083E5 str r2, [r3, #16]
32 0014 00401C40 .ADDRESS: .word 1075593216
33
34 @ 0 "" 2
35 .arm
36 .syntax unified
37 0018 0000A0E1 nop
38 001c 00D08BE2 add sp, fp, #0
39 @ sp needed
40 0020 04B09DE4 ldr fp, [sp], #4
41 0024 1EFF2FE1 bx lr
可以看到第32行已经发出了符号.ADDRESS
,但是它被代码包围了,没有指示跳过它。我相信它可以像指令一样被尝试执行。
也许彼得建议的更好的解决方案是
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
"str %0, [%2, %1]"
:: "r" (1<<17), "i" (16), "r" (ADDR) : "memory"
);
}