如果呢? ...好吧,试试吧:
typedef struct
{
unsigned int a[30];
unsigned int b;
unsigned int c;
unsigned int d;
} HELLO;
void more_fun ( unsigned int, unsigned int, HELLO );
HELLO b;
void fun ( void )
{
HELLO a;
a.a[7]=5;
a.b=6;
a.c=7;
a.d=8;
more_fun(1,2,a);
a.c=12;
more_fun(66,77,a);
b.c=12;
more_fun(44,55,b);
}
然后编译反汇编
arm-none-eabi-gcc -O2 -c fun.c -o fun.o
arm-none-eabi-objdump -D fun.o
看看你得到了什么......很明显我一直在修改/添加东西以查看实际发生的情况。我没想到会这样,但它实际上是按价值传递的。我期待它制作一个可销毁的副本,并传递一个指向它的指针。 arm abi 首先使用 r0-r3 (如果使用所有这些,则有规则),然后在这些用完时进入堆栈。在上述情况下,前两个单词在 r2 和 r3 中,另外 31 个在堆栈中,a 结构也在堆栈中用于 fun 函数,我得到的结构足够大,可以强制它使用 memcpy 而不是 a ldm/stms 系列。
但你真正的问题可能是什么。如果手臂寄存器不能保存“指针”,那么架构将如何工作?如果/当地址空间超过单个通用寄存器(迄今为止,该架构有基于寄存器的寻址指令),则将一些方案添加到架构中。分页非常流行,一些新的寄存器/地址保存高地址位或基地址,寄存器现在是偏移量而不是整个地址。到目前为止,我还没有在手臂上看到过这样的东西。
正如已经回答的那样,由于这是一个 C 指针问题而不是架构问题,因此答案严格在于 C 是如何为该架构实现的。并且使用像保证这样的词肯定会最终失败。除了架构是否会随着时间而改变之外,您没有理由假设任何两个编译器或同一编译器的任何两个版本或编译都会产生与另一个相同的结果,所以今天它可能会做一件事,但它可以/明天会做点什么。
至于你传递一个指针问题...试试看
您正在使用输出的编译器。然后,如果您只是想知道或认为编译器有问题,请检查已发布的调用约定,如果有(在本例中存在),并查看编译器生成的代码与调用约定的比较。如果您的测试 C 代码是真实的或真实的,那么这就是编译器传递该指针的方式,并且您的 asm 不仅可以而且必须从传递该指针的位置检索该指针,以便 c/asm 接口工作。
当然,如果你在你的 asm/c 接口中做任何太复杂的事情,它会增加你下次 abi 更改你的 c/asm 接口时失败的几率。 asm/c 接口总是存在一定程度的失败机会。对于任何平台上的任何编译器(除非您是编译器/汇编器的作者并确保您永远不会更改它)。
你几乎总是可以做的就是“试一试”,看看编译器如何生成调用,数据在哪里,如果编译器没有错误,那么它遵循约定,你可以依赖它(对于那个编译器),如果它有问题,那么由于有问题的编译器,无论有没有 asm,你的程序都可能会失败。