为了提高代码执行效率,内核源代码中有些地方直接使用了汇编语言编制。这就会涉及在两种语言编制的程序之间相互调用的问题。

  函数调用包括从一块代码到另一块代码之间的双向数据传递和执行控制转移。数据传递通过函数参数和返回值来进行。另外,我们还需要在进入函数是为函数的局部变量分配空间,并在函数退出时回收者部分空间。Intel 8086 CPU为控制传递提供了简单的指令,而数据的传递和局部变量存储空间的分配与回收则通过栈操作来实现。

  1.栈帧结构和控制转移权方式

大多数CPU的程序实现使用栈来支持函数调用操作。栈被用来传递函数参数、存储返回信息、临时保存寄存器原有值和存储局部数据。单个函数调用操作所使用的部分被称为栈帧(stack frame)结构。栈帧结构的两端由两个指针指定。寄存器ebp通常用作帧指针,esp用作栈指针。程序执行过程中,栈指针会随着数据的入栈和出栈而移动,因此函数中对大部分数据的访问都是基于帧指针ebp进行。

  对于函数A调用函数B的情况,传递给B的参数包含在A的栈帧中。当A调用B时,函数A的返回地址被压入栈中,该位置也明确指明A栈帧的结束处。而B的栈帧从随后的栈部分开始。B函数同样也使用栈来保存不能放在寄存器中的局部变量值。例如:由于通常CPU的寄存器数量有限而不能存放函数的所有局部数据,或者有些局部变量是数组或结构,因此必须使用数组或结构引用来访问。还有就是C语言地址操作符“&”被应用到一个局部变量上时,我们就需要为该变量生成一个地址,即为该变量的地址指针分配一块空间。最后,B函数会使用栈来保存调用任何其他函数的参数。

  栈是往小(低)地址方向扩展的,而esp指向当前栈顶处元素。通过使用push和pop指令我们可以把数据压入栈中或从栈中弹出。对于没有指定初始值的数据所需要的空间,我们可以通过把栈指针递减适当的值来做到。类似的可以回收已经分配的空间。

  指令CALL和RET用来处理函数调用和返回操作。调用指令CALL的作用是把返回地址压入栈中并且跳转到被调用函数开始处执行。返回地址是程序中紧随调用指令CALL后面的一条指令的地址。因此当被调用函数返回是就从该位置继续执行。返回指令RET用于弹出栈顶处的地址并跳转到该地址处。在使用该指令之前,应该先正确处理栈中内容,使得当前栈指针所指内容正是先前CALL指令保存的返回地址。另外,若返回值是一个整数或者一个指针,那么寄存器eax将被默认用来传递返回值。

  尽管某一个时刻只有一个函数在执行,但是我们还是需要确认在一个函数调用其他函数时,被调用者不会修改或覆盖调用者今后要用到的寄存器内容。因此Intel CPU采用了所有函数必须遵守的寄存器用法统一惯例。该惯例指明,寄存器eax、edx、ecx的内容必须由调用者自己负责保存。当函数A调用函数B时,B可以在不用保存这些寄存器的内容的情况下任意使用它们而不会毁坏函数A所需要的任何数据。另外,寄存器ebx、esi和edi的内容则必须由被调用者来保护。当被调用者需要使用到这些寄存器中的任何一个时,必须首先在栈中保存其内容,并在退出时恢复这些寄存器的内容。因为调用者A并不负责保存这些寄存器的内容,但可能在以后的操作中还需要用到原先的值。还有寄存器ebp和esp也必须遵守第二个惯例用法。

3.4 C与汇编程序的相互调用的更多相关文章

  1. A(51)和C(51)相互调用

    C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并可以调用汇编语言的子程序.用C语言设计开发微控制器程序已成为一种必然的趋势.Franklin C51是一种专门针对Intel 8051系列 ...

  2. Android和JavaScript相互调用的方法

    转载地址:http://www.jb51.net/article/77206.htm 这篇文章主要介绍了Android和JavaScript相互调用的方法,实例分析了Android的WebView执行 ...

  3. 多个Activity相互调用和Intent

    MainActivity.java和OtherActivity.java的相互调用 首先MainActivity.java是Android程序自带的,新建一个类OtherActiviy extends ...

  4. JS代码和OC代码的相互调用

    JS调用OC 很多应用里面或多或少的调用了网页,来达到绚丽的效果,所谓的JS调用OC.....举个例子吧,网页上有个按钮 点击按钮跳转界面,跳转的动作由OC的代码实现. OC调用JS 还是举个例子,我 ...

  5. C程序与Lua脚本相互调用

    Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows ...

  6. Unity3D中C#和js方法相互调用

    通过查找资料,Unity3D中C#和js要相互调用彼此的方法,js文件必须放在"Standard Assets". "Pro Standard Assets" ...

  7. Unity3d 脚本相互调用

    unity中三种调用其他脚本函数的方法 第一种,被调用脚本函数为static类型,调用时直接用  脚本名.函数名().很不实用…… 第二种,GameObject.Find("脚本所在物体名& ...

  8. Lua与C++相互调用

    {--1.环境--} 为了快速入手,使用了小巧快速的vc++6.0编译器 以及在官网下载了Lua安装包..官网地址{--http://10.21.210.18/seeyon/index.jsp--} ...

  9. 关于action script与js相互调用的Security Error问题

    大家都知道,as和js相互调用可以通过ExternalInterface.call和ExternalInterface.addCallback来进行. 比较好的做法是使用之前通过ExternalInt ...

随机推荐

  1. 使用Qt编写模块化插件式应用程序

    动态链接库技术使软件工程师们兽血沸腾,它使得应用系统(程序)可以以二进制模块的形式灵活地组建起来.比起源码级别的模块化,二进制级别的模块划分使得各模块更加独立,各模块可以分别编译和链接,模块的升级不会 ...

  2. Android网络传输中必用的两个加密算法:MD5 和 RSA

    MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明 ...

  3. 【HDOJ】1078 FatMouse and Cheese

    这道题目是典型的DFS+记忆化搜索, DP思想.符合:含重叠子问题,无后效性等特点. #include <cstdio> #include <cstring> #include ...

  4. SDUT2484 算术表达式的转换(表达式树)

    题目链接. 分析: 转换成表达式树,然后先序.中序.后序遍历. AC代码如下: #include <stdio.h> #include <string.h> #define m ...

  5. ubuntu14.04下交叉编译器的安装

    今天打算换个工作环境,在ubuntu下装交叉编译器,可谓一波三折.最后总算是装好了. 首先参照一下这位仁兄的博客http://blog.csdn.net/silleyj/article/details ...

  6. UVA10557- XYZZY(spfa+设置次数上限)

    题意:有N个房间,刚开始你位于1号房间,有100的能量值,你要到达N号房间,每两个房间之间有单向门相连接,你到达某个房间可以加上该房间的能量值, 如果你在未到达N号房间之前能量值耗尽,则死亡,否则胜利 ...

  7. 首届京东自有品牌科技周“京东点亮生活”圆满成功 - 课程公告板 - 京东内部论坛 - Powered by Discuz!

    首届京东自有品牌科技周"京东点亮生活"圆满成功 - 课程公告板 - 京东内部论坛 - Powered by Discuz! 首届京东自有品牌科技周"京东点亮生活" ...

  8. Promise in AngularJS

    What's promise Angular’s event system provides a lot of power to our Angular apps. One of the most p ...

  9. 搭建完整邮件系统(postfix+dovecot+clamAV+Spamassassin+amavisd-new)

    ============================ 相关软件: 1. 发送邮件 --- postfix 2. 身份认证 --- sasl2 3. 接收邮件 --- dovecot 4. 防病毒邮 ...

  10. Demo_敌军坦克生成,坦克移动(可以拓展发射子弹,敌军消失获取分数或者添加动画,声音功能)

    using UnityEngine; using System.Collections; public class Tank : MonoBehaviour { //坦克面积结构体对象 public ...