结构如何作为参数传递给汇编

时间:2015-05-06 04:01:08

标签: assembly x86 stdcall cdecl

如何在程序集中作为参数传递结构?

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

如果是这样,它们的顺序与正常参数相反?

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

3 个答案:

答案 0 :(得分:4)

在汇编中,所有投注均已关闭,您可以按照自己喜欢的方式传递参数,前提是调用者和被调用者同意如何完成。

在堆栈上放置参数,在堆栈上放置指针,将它们放入寄存器中,将它们存放在固定的内存位置,这完全取决于您。我已经看到一些参数在寄存器中传递的情况,而其他参数在堆栈上传递或通过引用传递。

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

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

一般来说,最好的方法是找出其他程序员正在做的事情并做同样的事情。要么是这样,要么很好地记录你的功能,以便用户知道如何调用它。

现在,如果您的程序集要调用或被其他语言调用,例如C,C ++,Fortran等,那么您需要研究由语言设计者建立的标准调用约定,这些约定通常也是取决于架构。例如,对于32位x86上的C,参数将在堆栈上传递,而对于Sparc,最多五个参数将在寄存器中传递,除此之外的任何参数都在堆栈上传递。

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

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

数组总是作为指针传递。

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

答案 1 :(得分:-1)

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

然后,该函数将此指针加载到某个寄存器中,并按其偏移量对结构的字段进行寻址。

答案 2 :(得分:-1)

结构与数组一样,通过引用传递,因此作为参数:它们只是一个32位参数(指向第一个结构成员的指针), 并且在cdeclstdcall的情况下,指针被推到堆栈上。

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

myarray dword 300 dup(?)
push offset myarray

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