Win知识 - 程序是怎样跑起来的——函数调用机制

简介: Win知识 - 程序是怎样跑起来的——函数调用机制

前面说了这么多,至此我们终于把阅读汇编语言源代码的准备工作完成了。让我们再来回顾一下代码清单10-2的内容。首先,让我们从MyFunc函数调用AddNum函数的汇编语言部分开始,来对函数的调用机制进行说明。函数调用是栈发挥大作用的场合。把代码清单10-2中的C语言源代码部分去除,然后再在各行追加注释,这时汇编语言的源代码就如代码清单10-4所示。这也就是MyFunc函数的处理内容。

代码清单10-4 函数调用的汇编语言代码①



(1)、(2)、(7)、(8)的处理适用于C语言中所有的函数,我们会在后面展示AddNum函数处理内容时进行说明。这里希望大家先关注一下(3)~(6)部分,这对了解函数调用的机制至关重要。

(3)和(4)表示的是将传递给AddNum函数的参数通过push入栈。在C语言的源代码中,虽然记述为函数AddNum(123,456),但入栈时则会按照456、123这样的顺序,也就是位于后面的数值先入栈。这是C语言的规定。(5)的call指令,把程序流程跳转到了操作数中指定的AddNum函数所在的内存地址处。在汇编语言中,函数名表示的是函数所在的内存地址。AddNum函数处理完毕后,程序流程必须要返回到编号(6)这一行。call指令运行后,call指令的下一行((6)这一行)的内存地址(调用函数完毕后要返回的内存地址)会自动地push入栈。该值会在AddNum函数处理的最后通过ret指令pop出栈,然后程序流程就会返回到(6)这一行。

(6)部分会把栈中存储的两个参数(456和123)进行销毁处理,也就是在第5章提到的栈清理处理。虽然通过使用两次pop指令也可以实现,不过采用esp寄存器加8的方式会更有效率(处理1次即可)。对栈进行数值的输入输出时,数值的单位是4字节。因此,通过在负责栈地址管理的esp寄存器中加上4的2倍8,就可以达到和运行两次pop命令同样的效果。虽然内存中的数据实际上还残留着,但只要把esp寄存器的值更新为数据存储地址前面的数据位置,该数据也就相当于被销毁了。

前面已经提到,push指令和pop指令必须以4字节为单位对数据进行入栈和出栈处理。因此,AddNum函数调用前和调用后栈的状态变化就如图10-4所示。长度小与4字节的123和456这些值在存储时,也占用了4字节的栈区域。



图10-4 AddNum函数调用前后栈的状态变化

代码清单10-1中列出的C语言源代码中,有一个处理是在变量c中存储AddNum函数的返回值,不过在汇编语言的源代码中,并没有与此对应的处理。这是因为编译器有最优化功能。最优化功能是编译器在本地代码上费尽功夫实现的,其目的是让编译后的程序运行速度更快、文件更小。在代码清单10-1中,由于存储着AddNum函数返回值的变量c在后面没有被用到,因此编译器就会认为“该处理没有意义”,进而也就没有生成与之对应的汇编语言代码。在编译代码清单10-1的代码时,应该会出现“警告 W8004 Sample4.c 11: 'c'的赋值未被使用(函数MyFunc)”这样的警告消息。

Ps:注脚

① 在函数的入口处把寄存器ebp的值入栈保存(代码清单10-4(1)),在函数的出口处出栈(代码清单10-4(7)),这是C语言编译器的规定。这样做是为了确保函数调用前后ebp寄存器的值不发生变化。

目录
相关文章
MASM32编程更新SysInfo,运行时程序窗口玩失踪
MASM32编程更新SysInfo,运行时程序窗口玩失踪
|
8月前
|
Linux Shell vr&ar
进程从代码到二进制到运行时的过程
【4月更文挑战第18天】Linux系统中二进制程序的格式,介绍了ELF(Executable and Linkable Format)格式。
|
8月前
|
自然语言处理 Java 编译器
程序是如何运行的(一)
程序是如何运行的(一)
|
存储 自然语言处理 编译器
程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #
程序的编译与链接(C语言为例) #代码写好后到运行期间要经过怎样的过程呢?# 粗略版 #
|
存储 C语言
Win知识 - 程序是怎样跑起来的——函数内部的处理
Win知识 - 程序是怎样跑起来的——函数内部的处理
90 0
Win知识 - 程序是怎样跑起来的——函数内部的处理
|
程序员 C语言
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
150 0
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
|
存储 API C语言
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
148 0
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
|
存储 程序员 编译器
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆
127 0
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆