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

Assembly 结构如何在程序集中作为参数传递,assembly,x86,stdcall,cdecl,Assembly,X86,Stdcall,Cdecl,结构如何在程序集中作为参数传递 由于结构的大小大于正常大小,各个字段是否按顺序传递 如果是,它们是否与正常参数的顺序相反 cdecl和stdcall之间有什么区别吗?在大多数情况下,结构作为指向结构开头的指针传递 然后,函数将该指针加载到一些寄存器中,并通过偏移量对结构的字段进行寻址。结构与数组一样,通过引用传递,因此作为参数:它们只是一个32位参数(指向第一个结构成员的指针), 在cdecl和stdcall的情况下,该指针被推到堆栈上 如果按值传递数据结构,这意味着您必须将堆栈上结构的每个成员

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

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

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


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

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


然后,函数将该指针加载到一些寄存器中,并通过偏移量对结构的字段进行寻址。

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

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

myarray dword 300 dup(?)
push offset myarray

现在,此数组已通过引用(第一个成员的指针)推送。

在汇编中,所有赌注都已取消,只要调用者和被调用者就如何传递参数达成一致,您就可以以任何方式传递参数

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

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

(你想看《疯狂》吗?请阅读《著名》一书,该书收集了286体系结构中所有已知的软件中断调用。实际上,你在MS-DOS下安装的每一个软件都在pot中添加了一些新的软件中断,而且它们都有自己的调用约定,而且许多都相互冲突。)

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


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

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

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

数组始终作为指针传递


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

这是x86还是x86_64?您使用的是什么汇编程序?虽然我对x86_64很好奇,但它只是标准的x86?其区别在于两者之间的调用约定不同,x86_64通过寄存器传递,前六个整数参数(从左起)通过RDI、RSI、RDX、RCX、R8和R9传递,以该顺序传递,而x86以相反的顺序在堆栈上传递。我现在还没有非标准类型大小结构的答案。我将稍微讨论一下。显然,结构是通过引用(通过指针)传递的,它取决于编译器,无论是在EAX/AX中传递还是在堆栈上传递。显然,由于所创建的非线程安全条件,大多数编译器在类和结构方面不遵循调用约定。这里有一个链接,讨论GCC和Visual C++之间的差异,它包含了维基百科的其他链接,等等。你应该添加一个你正在考虑的示例代码片段…你是在问C结构和数组,还是其他问题?“如果你通过值传递数据结构…”,请注意C确实是通过值传递结构的(实际上C通过值传递所有内容,因为即使数组也被认为是衰减为指针的,然后通过值传递),这就是函数不能修改原始值。错误。结构从不通过引用传递;这样做将完全击败使用显式指针到结构(或C++引用)的目的。正如hyde所说,实际上从未“传递”数组,只传递指向其第一个成员的指针。这只是数组的一个怪癖,不适用于其他任何东西。如果您看到其他情况,则可能是编译器引入的优化,它注意到它可以在不破坏语言语义的情况下进行优化。@Martin:Windows x64在C按值传递结构时,确实通过隐藏引用传递结构。(请注意,它为arg指向的命名本地创建了一个副本,因为调用方“拥有”该内存。这是一个遗漏的优化,因为调用方的副本在调用后已失效,它可能会让被调用方销毁它,并且没有其他线程引用它。)因此,无论如何,它不是对调用方原始对象的引用,我想这就是你的观点。其他调用约定(如x86-64 System V)会将整个结构复制到堆栈中。这不是C