以下是我的问题的背景:
在我的项目中,在初始化堆栈之前从程序集文件中调用C函数。由于堆栈未初始化,因此该函数不得使用堆栈。
是否有可能使用某些“pragma like”命令强制gcc不使用具有该特定功能的堆栈?
其他信息:我的工作目标是将以前使用ARMASM编译的项目转换为gcc。所以在ARMASM中,在堆栈初始化之前调用这个C函数是有效的。也许最终的答案是在gcc中不可能做到这一点......
下面是汇编代码中调用的C函数的ELF列表的摘录(正如您所看到的,我尝试了always_inline,但是当从汇编中调用时,这似乎不够):
000049d0 <CInit_Init>:
__attribute__((always_inline)) extern void CInit_Init(void) {
49d0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
49d4: e28db000 add fp, sp, #0
__attribute__((always_inline)) void COM1_Init(void);
__attribute__((always_inline)) extern inline void COM1_Init_I(void) {
// Skip if already enabled
if (TEST_BIT_CLR(HwrSysControl1, HwSysControl1UartEnable)) {
49d8: e59f3038 ldr r3, [pc, #56] ; 4a18 <CInit_Init+0x48>
49dc: e5933000 ldr r3, [r3]
49e0: e2033c01 and r3, r3, #256 ; 0x100
49e4: e3530000 cmp r3, #0
49e8: 1a000007 bne 4a0c <CInit_Init+0x3c>
HwrUart1Control = (
49ec: e59f3028 ldr r3, [pc, #40] ; 4a1c <CInit_Init+0x4c>
49f0: e59f2028 ldr r2, [pc, #40] ; 4a20 <CInit_Init+0x50>
49f4: e5832000 str r2, [r3]
HwUartControlDataLength8|
HwUartControlFifoEnable|
HwUartControlRate115200);
BIT_SET(HwrSysControl1, HwSysControl1UartEnable);
49f8: e59f3018 ldr r3, [pc, #24] ; 4a18 <CInit_Init+0x48>
49fc: e59f2014 ldr r2, [pc, #20] ; 4a18 <CInit_Init+0x48>
4a00: e5922000 ldr r2, [r2]
4a04: e3822c01 orr r2, r2, #256 ; 0x100
4a08: e5832000 str r2, [r3]
COM1_Init_I();
}
4a0c: e28bd000 add sp, fp, #0
4a10: e49db004 pop {fp} ; (ldr fp, [sp], #4)
4a14: e12fff1e bx lr
4a18: 80000100 .word 0x80000100
4a1c: 800004c0 .word 0x800004c0
4a20: 00070001 .word 0x00070001
提前致谢!
答案 0 :(得分:2)
只需设置堆栈。否则,如果你不希望堆栈没有局部变量,并且没有足够的代码,你没有用完寄存器,不要在这个函数中调用任何函数,等等。如果你真的需要变量,那么使用全局变量。如果导致代码用完寄存器和全局变量,编译器不能在不使用堆栈的情况下生成代码。没有编译器开关会发明存储,我不相信一个编译器有一些它可能会尝试使用的非堆栈非标准技巧..
简单,没有局部变量,甚至不需要中间寄存器:
unsigned int fun ( unsigned int a, unsigned int b )
{
return(a+b);
}
没有堆叠:
00000000 <fun>:
0: e0810000 add r0, r1, r0
4: e12fff1e bx lr
在调用初始C代码后,您总是可以更改堆栈,在C调用之前需要一条指令来设置堆栈,只需设置堆栈指针即可。你不需要所有的堆栈指针,只需要一个。要么设置堆栈指针,要么在汇编程序而不是C中写入函数。无论如何,应该在com端口之前初始化堆栈。它是一个指令,两个字位置,你打电话给C所以成本可以忽略不计。
.globl _start
_start:
b reset
reset:
ldr sp,=0x20008000
bl more_fun
b .
.globl fun
fun:
bx lr
.globl fun_out
fun_out:
bx lr
unsigned int fun ( unsigned int , unsigned int );
void fun_out ( unsigned int, unsigned int, unsigned int, unsigned int );
unsigned int more_fun ( unsigned int a, unsigned int b, unsigned int c )
{
unsigned int d;
d = fun(a,b);
fun_out(a,b+c,b,a+c);
}
关于指令,两个单词,你可以调用C
4: e59fd00c ldr sp, [pc, #12] ; 18 <fun_out+0x4>
8: eb000003 bl 1c <more_fun>
...
18: 20008000 andcs r8, r0, r0
0000001c <more_fun>:
1c: e92d4070 push {r4, r5, r6, lr}
20: e1a05002 mov r5, r2
24: e1a06000 mov r6, r0
28: e1a04001 mov r4, r1
2c: ebfffff7 bl 10 <fun>
30: e1a00006 mov r0, r6
34: e0853006 add r3, r5, r6
38: e0851004 add r1, r5, r4
3c: e1a02004 mov r2, r4
40: ebfffff3 bl 14 <fun_out>
44: e8bd8070 pop {r4, r5, r6, pc}
答案 1 :(得分:1)
您有两个选择:
gcc -c cfile.c -S -o asmfile.s
。那会的
可能会省你一些工作。我宁愿立即拥有一个有效的堆栈。