我感兴趣的是在执行编译Visual C ++的汇编代码的call
指令时会发生什么。
我认为发生的是调用指令本身将所有上下文压入堆栈(寄存器内容,PC,...)并更新PC。但话说回来,我想知道是否所有背景都被推动了。在许多情况下,并非所有寄存器都在所调用的函数中使用。编译器是否检测到这一点并且仅推送由该函数修改的上下文,或者是否在硬件级别推送所有上下文实现的所有上下文始终如此?
答案 0 :(得分:5)
这一切都取决于ABI(Application Binary Interface),它指示调用者或被调用者是否将事物推入堆栈。既然你没有指定一个平台(虽然Visual Studio的含义是x86),答案取决于。
通常,调用者无法知道被调用函数的作用,因此编译器无法根据函数内部的信息进行优化。
通常,将上下文推送到堆栈不会在任何平台上自动执行,但是有几个平台具有宏和优化指令以快速完成。通常,从堆栈中自动推送和弹出的唯一东西就是PC。
编辑:对于x86,有几个ABI。您应该查看此Wiki reference以查看所有内容(cdecl,stdcall等)。每个都有关于调用者或被调用者是否保存上下文的不同规则。
答案 1 :(得分:1)
指令CALL
不会将堆栈中的寄存器推送出去。它仅推送函数应返回的地址。
INT
指令(与调用类似)也会推送FLAGS
寄存器的内容。
如果程序在函数调用期间需要保留一些其他寄存器,则需要通过显式 push
指令将这些寄存器存储在堆栈中,然后通过{{恢复它们1}}说明。
当我们谈论高级语言时,应该存储什么以及确切地如何仅依赖于编译器。编译器可以自由使用任何约定,但通常它们遵循标准约定,以便能够链接用不同语言编写的模块。
在汇编编程中,保留策略完全取决于程序员。他可以根据自己的编程目标使用一些标准约定或自定义约定。