7

结构体如何在汇编中作为参数传递?

由于结构的大小比正常大,各个字段是否按顺序传递?

如果是这样,它们是否像正常参数一样以相反的顺序排列?

cdecl 和 stdcall 之间有什么区别吗?

4

3 回答 3

6

在汇编中,所有的赌注都是关闭的,你可以以任何你喜欢的方式传递参数,只要调用者和被调用者就如何完成达成一致。

将参数放在堆栈上,将指向它们的指针放在堆栈上,将它们放入寄存器,将它们存储在固定的内存位置,这一切都取决于你。我见过一些参数是在寄存器中传递的,而另一些是在堆栈上传递或通过引用传递的。

如何转移控制权也取决于您。执行“调用”指令或软件中断。旧的 PDP-10 架构有五种不同的调用子程序的方式,你必须知道使用哪一种。IBM-360 架构也有多种方式。

(你想看疯狂吗?阅读著名的中断列表,它是所有可用于 286 架构的已知软件中断调用的集合。实际上,您在 MS-DOS 下安装的每个软件都添加了一些新的软件中断,他们每个人都有自己的调用约定,其中许多相互冲突。)

一般来说,你最好的方法是找出其他程序员在做什么,然后做同样的事情。要么,要么很好地记录您的函数,以便用户知道如何调用它。


现在,如果您的程序集要调用或被另一种语言调用,例如 C、C++、Fortran 等,那么您需要研究由语言设计者建立的标准调用约定,这些约定通常也依赖于建筑学。例如,对于 32 位 x86 上的 C,参数将在堆栈上传递,而对于 Sparc,最多五个参数将在寄存器中传递,超出的任何参数都将进入堆栈。

至于结构,C 标准要求将它们解包,并将各个元素作为单独的参数传递,由被调用者重新组装成一个结构。如果结构非常大,这可能会非常浪费,因此最好将指针传递给结构。

如果函数返回一个结构,调用者分配空间来接收它,并将指向该空间的指针作为“秘密”参数传递给函数。

数组总是作为指针传递。

对于 Fortran,所有内容都是通过引用传递的,这意味着可以将值返回给任何参数。甚至常量也被存储在内存中的某个地方,指向它们的指针被传递给被调用的子例程。(因此可能会意外更改常量的值。)

于 2016-07-07T01:53:09.083 回答
0

结构和数组一样,通过引用传递,因此作为参数:它们只是一个 32 位参数(指向第一个结构成员的指针),并且在 和 的情况下该指针被压入cdecl堆栈stdcall

如果您通过value传递数据结构,这意味着您必须将堆栈上结构的每个成员推送到被调用方,这对性能有很大影响——特别是对于大型结构。

myarray dword 300 dup(?)
push offset myarray

现在这个数组已经被引用(第一个成员的指针)推送了。

于 2015-05-06T07:19:09.150 回答
-1

在大多数情况下,结构体作为指向结构体开头的指针传递。

然后该函数将这个指针加载到某个寄存器中,并通过它们的偏移量来寻址结构的字段。

于 2015-05-06T07:15:39.133 回答