汇编函数调用是否导致所有寄存器被压入堆栈?
Does the assembly function call cause all registers to be pushed onto the stack?
我对执行 Visual C++ 汇编代码的 call
指令时发生的情况很感兴趣。
我认为发生的是调用指令本身将所有上下文推入堆栈(寄存器内容、PC 等)并更新 PC。但话又说回来,我想知道是否所有上下文都被推送了。在许多情况下,并非所有寄存器都在调用的函数中使用。编译器是否检测到这一点并仅推送由函数修改的上下文,或者推送所有在硬件级别如此廉价实现的上下文以致于它总是完成?
这一切都取决于 ABI (Application Binary Interface),它决定是调用者还是被调用者将东西压入堆栈。由于您没有指定平台(尽管 Visual Studio 有点暗示 x86),答案取决于。
一般情况下,调用者无法知道被调用的函数会做什么,所以编译器无法根据函数内部的信息进行优化。
通常,将上下文推入堆栈不会在任何平台上自动执行,但一些平台有宏和优化指令可以快速执行此操作。通常唯一自动从堆栈中压入和弹出的是PC。
编辑:对于 x86,有几个 ABI。您应该查看此 Wiki reference 以查看所有内容(cdecl、stdcall 等)。关于调用者或被调用者是否保存上下文,每个规则都有不同的规则。
指令CALL
不会将寄存器压入堆栈。它只推送函数应该 return 的地址。
INT
指令(类似于调用)也推送 FLAGS
寄存器的内容。
如果程序在函数调用过程中需要保留一些其他的寄存器,需要通过explicitpush
指令将这些寄存器存入栈中,然后再按照 pop
说明恢复它们。
当我们谈论高级语言时,要存储什么以及具体如何存储仅取决于编译器。编译器可以自由使用任何约定,但通常它们会遵守标准约定,以便为 link 以不同语言编写的模块提供能力。
在汇编编程中,保留策略完全取决于程序员。他可以根据自己的编程目标使用一些标准约定或自定义约定。
我对执行 Visual C++ 汇编代码的 call
指令时发生的情况很感兴趣。
我认为发生的是调用指令本身将所有上下文推入堆栈(寄存器内容、PC 等)并更新 PC。但话又说回来,我想知道是否所有上下文都被推送了。在许多情况下,并非所有寄存器都在调用的函数中使用。编译器是否检测到这一点并仅推送由函数修改的上下文,或者推送所有在硬件级别如此廉价实现的上下文以致于它总是完成?
这一切都取决于 ABI (Application Binary Interface),它决定是调用者还是被调用者将东西压入堆栈。由于您没有指定平台(尽管 Visual Studio 有点暗示 x86),答案取决于。
一般情况下,调用者无法知道被调用的函数会做什么,所以编译器无法根据函数内部的信息进行优化。
通常,将上下文推入堆栈不会在任何平台上自动执行,但一些平台有宏和优化指令可以快速执行此操作。通常唯一自动从堆栈中压入和弹出的是PC。
编辑:对于 x86,有几个 ABI。您应该查看此 Wiki reference 以查看所有内容(cdecl、stdcall 等)。关于调用者或被调用者是否保存上下文,每个规则都有不同的规则。
指令CALL
不会将寄存器压入堆栈。它只推送函数应该 return 的地址。
INT
指令(类似于调用)也推送 FLAGS
寄存器的内容。
如果程序在函数调用过程中需要保留一些其他的寄存器,需要通过explicitpush
指令将这些寄存器存入栈中,然后再按照 pop
说明恢复它们。
当我们谈论高级语言时,要存储什么以及具体如何存储仅取决于编译器。编译器可以自由使用任何约定,但通常它们会遵守标准约定,以便为 link 以不同语言编写的模块提供能力。
在汇编编程中,保留策略完全取决于程序员。他可以根据自己的编程目标使用一些标准约定或自定义约定。