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寄存器的值不发生变化。

目录
相关文章
|
21天前
|
移动开发 小程序 前端开发
H5和小程序有什么区别
H5和小程序有什么区别
一个非常简单的函数为什么会崩溃
一个非常简单的函数为什么会崩溃
|
存储 编译器 API
Win32汇编:过程与宏调用
在计算机领域,堆栈是一个不容忽视的概念,堆栈是一种`后进先出(LIFO,Last-In,First-Out)`的数据结构,这是因为最后压入堆栈的值总是最先被取出,而新数值在执行PUSH压栈时总是被加到堆栈的最顶端,数据也总是从堆栈的最顶端被取出,堆栈是个`特殊的存储区`,主要功能是暂时存放数据和地址,通常用来保护断点和现场.
89 0
|
开发工具 git
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
477 0
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
|
存储 C语言
Win知识 - 程序是怎样跑起来的——函数内部的处理
Win知识 - 程序是怎样跑起来的——函数内部的处理
56 0
Win知识 - 程序是怎样跑起来的——函数内部的处理
|
程序员 C语言
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
111 0
Win知识 - 程序是怎样跑起来的——了解程序运行方式的必要性
关于 qt程序退出出现“已停止工作”程序奔溃问题 的解决方法
关于 qt程序退出出现“已停止工作”程序奔溃问题 的解决方法
关于 qt程序退出出现“已停止工作”程序奔溃问题 的解决方法
|
编译器 C语言
Win知识 - 程序是怎样跑起来的——汇编语言和本地代码是一一对应的
Win知识 - 程序是怎样跑起来的——汇编语言和本地代码是一一对应的
112 0
Win知识 - 程序是怎样跑起来的——汇编语言和本地代码是一一对应的
|
存储 API C语言
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
115 0
Win知识 - 程序是怎样跑起来的——应用和硬件无关?
|
存储 程序员 编译器
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆
96 0
Win知识 - 程序是怎样跑起来的——程序加载时会生成栈和堆