C ARM中基于堆栈结构的调用约定?

C ARM中基于堆栈结构的调用约定?,c,struct,arm,C,Struct,Arm,如何将基于堆栈的结构传递给ARM汇编中的子例程 例如: typedef struct SomeStruct { uint32_t one; uint32_t two; uint32_t three; uint32_t four; } SomeStruct; void SomeFunction(uint32_t someValue, SomeStruct someStruct, uint32_t otherValue); 在这种情况下,该结构将如何通过?我的猜

如何将基于堆栈的结构传递给ARM汇编中的子例程

例如:

typedef struct SomeStruct { 
    uint32_t one;
    uint32_t two;
    uint32_t three;
    uint32_t four;
} SomeStruct;

void SomeFunction(uint32_t someValue, SomeStruct someStruct, uint32_t otherValue);
在这种情况下,该结构将如何通过?我的猜测是:

r0-someValue r1-someStruct.one r2-someStruct.2 r3-someStruct.3 *sp-someStruct.four *sp,4-其他值
这是正确的还是发生了其他事情?还是只传递结构基于sp的地址?

这里有一个ARM ABI的过程调用标准:

ARM有不止一个ABI,64位ARM也有更多ABI,但只要看看这一个,相关部分就是5.5参数传递。乍一看,我认为C.5说的没错,这个结构将在r1-r3和堆栈之间拆分


B.1可以将复合类型的参数替换为指向内存中副本的指针,但它在C中不适用,因为调用者和被调用者都必须将SomeStruct作为完整类型才能按值传递。

这里有一个ARM ABI的过程调用标准:

ARM有不止一个ABI,64位ARM也有更多ABI,但只要看看这一个,相关部分就是5.5参数传递。乍一看,我认为C.5说的没错,这个结构将在r1-r3和堆栈之间拆分


B.1可以用指向内存中副本的指针替换复合类型的参数,它在C中永远不适用,因为调用者和被调用者都必须有SomeStruct作为完整类型才能按值传递。

现在我想起来了,我的猜测听起来很愚蠢。除非你的结构非常小,否则直接传递结构并不常见。如果只传递一个指向该结构的指针,调用该函数的开销就会减少。@TJD:这是有问题的,因为该参数在逻辑上是一个副本。因此,如果调用方执行某个函数1,我的全局结构,1;如果&someStruct==&my\u global\u struct,则被调用方会执行该操作,当然,这一定是false。因此调用约定可以传递一个指针,这可能会有所帮助,但被调用方可能仍然需要一个副本,在这种情况下,这不会减少开销。@SteveJessop,是的,如果您确实需要一个副本,那么您将不得不支付相应的费用—您始终可以自己制作副本。将函数定义为void SomeFunction uint32\u t someValue、const SomeStruct*SomeStruct、uint32\u t otherValue,然后在函数中定义SomeStruct copy=*SomeStruct;。现在我想起来了,我的猜测听起来很愚蠢。除非你的结构非常小,否则直接传递结构是不常见的。如果只传递一个指向该结构的指针,调用该函数的开销就会减少。@TJD:这是有问题的,因为该参数在逻辑上是一个副本。因此,如果调用方执行某个函数1,我的全局结构,1;如果&someStruct==&my\u global\u struct,则被调用方会执行该操作,当然,这一定是false。因此调用约定可以传递一个指针,这可能会有所帮助,但被调用方可能仍然需要一个副本,在这种情况下,这不会减少开销。@SteveJessop,是的,如果您确实需要一个副本,那么您将不得不支付相应的费用—您始终可以自己制作副本。将函数定义为void SomeFunction uint32\u t someValue、const SomeStruct*SomeStruct、uint32\u t otherValue,然后在函数中定义SomeStruct copy=*SomeStruct;。我没有特别研究ARM ABI,但是通过让调用方传递地址来处理结构的传递和返回是非常常见的。如果调用的函数是用C编写的,那么地址就不会暴露给用户代码;相反,编译器通常会生成代码来复制结构。如果一个例程只被调用一次,调用方进行复制会更好,但是大多数例程被调用的次数足够多,这样被调用的代码进行复制会更有效。我没有特别研究ARM ABI,但是通过让调用方传递地址来处理结构的传递和返回是非常常见的。如果调用的函数是用C编写的,那么地址就不会暴露给用户代码;相反,编译器通常会生成代码来复制结构。如果一个例程只被调用一次,那么调用方进行复制会更好,但是大多数例程被调用的次数足够多,这样被调用的代码进行复制会更有效。