现今,完全用汇编书写的程序是非常少的。编译器能很好地将高级语言转换成有效的机器代码。因为用高级语言书写代码非常容易,所以高级语言变得很流行。此外,高级语言比汇编语言更容易移植!

当使用汇编语言时,我们经常将它使用在代码中的一小部分上。有两种使用汇编语言的方法:在C中调用汇编子程序或内嵌汇编。内嵌汇编允许程序员把汇编语句直接放入到C代码中。这样是非常方便的;但是,内嵌汇编同样存在缺点。汇编语言的书写格式必须是编译器使用的格式。目前没有一个编译器支持NASM格式。不同的编译器要求使用不同的格式。Borland和Microsoft要求使用MASM格式。DJGPP和Linux中gcc要求使用GAS格式。在PC机上,调用汇编子程序是更标准的技术。

在C中使用汇编程序通常是因为以下几个原因:

1、需要直接访问计算机的硬件特性,而用C语言很难或不可能做到。

2、程序执行必须尽可能地快,而且相比于编译器,程序员手动优化的代码更好。

最后一个原因不像它以前一样有根据。因为这些年编译器技术提高了,而且编译器通常可以产生非常有效的代码(特别是当开启编译器优化的时候)。调用汇编程序的缺点:可移植性和可读性减弱了。

绝大部分的C调用约定已经确定了。但是,还需要描述一些额外的特征。

保存寄存器

首先, C假定子程序保存了下面这几个寄存器的值:EBX,ESI,EDI, EBP,CS,DS,SS,ES。这并不意味着不能在子程序内部修改它们。相反,它表示如果子程序改变了它们的值,那么在子程序返回之前必须恢复它们的原始值。EBX,ESI和EDI的值不能被改变,因为C将这些寄存器用

于寄存器变量。通常都是使用堆栈来保存这些寄存器的原始值。

函数名

大多数C编译器都在函数名和全局或静态变量前附加一个下划线字符。例如,函数名f将指定为_f。因此,如果这是一个汇编程序,那么它必须标记为_f,而不是f。Linux gcc编译器并不附加任何字符。在可

执行的Linux ELF下,对于C函数f,你只需要简单使用函数名f即可。但是,DJGPP的gcc却附加了一个下划线。注意,在汇编程序skeleton中(图1.7),主程序函数名是_asm main。

传递参数

按照C调用约定,一个函数的参数将以一定顺序压入栈中,这个顺序与它们出现在函数调用里的顺序相反。考虑这条C语句:printf("x = %d\n",x); 图4.11展示了如何编译这条语句(用等价的NASM格式)。图4.12展示了执行完printf函数的开始部分后,堆栈的状态。printf函数一个可以携带任意个参数的C语言库函数。C调用约定的规则就是专门为允许这些类型的函数而规定的。 因为format字符串的地址最后压入堆栈,所以不管有多少参数传递到函数,

计算局部变量的地址

找到定义在data或bss段的变量的地址是非常容易的。基本上,连接程序做的就是这件事情。但是,要计算出在堆栈上的一个局部变量(或参数)的地址就不简单了。可是,当调用子程序的时候,这种需求是非常普通的。考虑传递一个变量(让我们称它为x)的地址到一个函数(让我们称它为foo)的情况。如果x处在堆栈的EBP ¡ 8的位置,你不可以这样使用:

mov       eax, ebp - 8

为什么?因为指令MOV储存到EAX里的值必须能由汇编器计算出来(也就是说,它最后必须是一个常量)。但是,有一条指令能做这种需求的计算。它就是LEA (即Load Effective Address,载入有效地址)。下面的代码就能计算出x的地址并将它储存到EAX中:

lea         eax, [ebp - 8]

现在EAX中存有了x的地址,而且当调用函数foo的时候,就可以将其压入到栈中。不要搞混了,这条指令看起来是从[EBP-8]中读数据;然而,这并不正确。LEA指令永远不会从内存中读数据。它仅仅计算出一个将会被其它指令使用到的地址,然后将这个地址储存到它的第一个操作数里。因为它并没有实际读内存,所以不指定内存大小(例如: dword)是必须的或说是允许的。

返回值

返回值不为空的C函数执行完后会返回一个值。C调用约定规定了这个要如何去做。返回值需通过寄存器传递。所有的整形类型(char,int,enum,等)通过EAX寄存器返回。如果它们小于32位,那么储存到EAX的时候,它们将被扩展成32位。(它们如何扩展取决于是有符号类型还是无符号类型。) 64位的值通过EDX:EAX寄存器对返回。浮点数储存在数学协处理器中的ST0寄存器中。(这个寄存器将在浮点数这一章来讨论。)

其它调用约定

所有的80x86 C编译器中都支持上面描述的标准C调用约定的规则。通常编译器也支持其它调用约定。当与汇编语言进行接口时,知道编译器调用你的函数时使用的是什么调用约定是非常重要的。通常,缺省时,使用的是标准的调用约定;但是,并不总是这一种情况4。使用多种约定的编译器通常都拥有可以用来改变缺省约定的命令行开关。它们同样提供扩展的C语法来为单个函数指定调用约定。但是,各个编译器的这些扩展标准可以是不一样的。

GCC编译器允许不同的调用约定。一个函数的调用约定可以通过扩展语法attribute 明确指定。例如,要声明一个返回值为空的函数f,它带有一个int参数,使用标准调用约定,需使用下面的语法来声明它的原型:

void   f ( int ) _attribute_(( cdecl ));

GCC同样支持标准call 调用约定。通过把cdecl替换成stdcall,上面的函数可以指定为使用这种约定。stdcall约定和cdecl约定的不同点是stdcall要求子程序将参数移除出栈(和Pascal调用约定一样)。因此,stdcall调用约定只能使用在带有固定参数的函数上(也就是说,不可以是函数printf和scanf)。

GCC同样支持称为regparm 的约定,这种约定告诉编译器前3个整形参数通过寄存器传递给函数,而不是通过堆栈。这是许多编译器支持的一个共同的优化模式。

Borland和Microsoft使用一样语法来声明调用约定。它们在C代码中加上关键字_cdecl和_stdcall。这些关键字用来修饰函数。在原型声明中,它们出现在函数名的前面例如,上面的函数f用Borland和Microsoft定义如下:

void _cdecl f ( int );

每种调用约定都有各自的优缺点。cdecl调用约定的主要优点是它非常简单而且非常灵活。它可以用于任何类型的C函数和C编译器。使用其它约定会限制子程序的可移植性。它的主要缺点是与其它约定相比它执行较慢而且使用更多的内存(因为函数的每次调用都需要用代码将参数移除出

栈。)。

stdcall调用约定的主要优点是相比于cdecl它使用较少的内存。在CALL指令之后,不需要清理堆栈。它的主要缺点是它不能使用于可变参数的函数。

使用寄存器传递参数的调用约定的优点是速度非常快。主要缺点是这种约定太复杂。有些参数可能在寄存器中,而另一些可能在堆栈中。

在汇编程序中调用C函数

C与汇编接口的一个主要优点是允许汇编代码访问大型C库和用户写的函数。例如,如果你想调用一下scanf函数来从键盘读一个整形,该怎么办?图4.14展示了完成这件事的代码。需要记住的非常重要的一点就是scanf函数遵循字面意义的C调用标准。这就意味着它保存了EBX,ESI和EDI寄存器的值;但是,EAX,ECX和EDX寄存器的值可能会被修改。事实上,EAX肯定会被修改,因为它将保存scanf调用的返回值。至于与C接口的其它例子,可以看用来产生asm io.obj的asm io.asm文件中的代码。

c 汇编语言用标准函数代替,C与汇编的接口技术相关推荐

  1. 汇编与接口技术期末复习笔记(1)—— 汇编部分

    文章目录 0. 计组先导知识 0.1 进位计数制 0.2 计算机中数和字符的表示 1. 基础知识 1.1 汇编语言 1.2 硬件接口 2. 80x86计算机组织 2.1 计算机系统 2.2 8086微 ...

  2. 汇编与接口技术课程总结1——汇编程序debug调试

    实验目的: 进一步学习汇编语言基本指令使用方法: 学习DEBUG调试工具的基本使用方法:掌握debug调试命令a.u.r.d.t.g等 逐条观察程序指令的执行过程,理解指令的功能,理解程序自动.顺序地 ...

  3. 汇编与接口技术实验报告

    文章目录 8254A不同工作方式的实验 利用8255A实现LED流水灯点亮实验 8259中断实验 A/D D/A 转换实验 8254A不同工作方式的实验 一.实验目的 掌握8254A和微机接口的连接方 ...

  4. 微型计算机原理daa,单片微机原理、汇编与C51及接口技术(第2版)

    单片微机原理.汇编与C51及接口技术(第2版) 语音 编辑 锁定 讨论 上传视频 <单片微机原理.汇编与C51及接口技术(第2版)>是2013年清华大学出版社出版的图书,作者是朱定华.戴颖 ...

  5. 汇编语言笔记——接口技术与编程

    文章目录 传送门 储存系统与技术 材料 高速储存器缓冲储存器(Cache) 材料,局部性,访问方式 Cache全相联映射 Cache交换与一致性 单核CPU一致性处理 多核CPU的MESI协议 主储存 ...

  6. 【微机原理与接口技术学习实践】汇编语言程序设计初步——debug编写调试指令序列

    halo~我是bay_Tong桐小白 本文内容是桐小白个人对所学知识进行的总结和分享,知识点会不定期进行编辑更新和完善,了解最近更新内容可参看更新日志,欢迎各位大神留言.指点 [微机原理与接口技术学习 ...

  7. 微型计算机汇编语言与接口技术答案,32位微机原理、汇编语言及接口技术教程课后习题答案.doc...

    32位微机原理.汇编语言及接口技术教程课后习题答案.doc 16/32位微机原理.汇编语言及接口技术教程部分习题参考解答第1章 微型计算机系统概述习题1.2什么是通用微处理器.单片机(微控制器).DS ...

  8. 北京工业大学微型计算机接口技术考试,汇编语言微机原理及接口技术期末试卷含答案.doc...

    汇编语言微机原理及接口技术期末试卷含答案.doc 1 北京大学 北京 综合 100 95.80 100 100 2 清华大学 北京 理工 94.72 100 85.10 92.17 3 复旦大学 上海 ...

  9. 汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案

    汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案 1. 8086/8088 CPU的地址总线有多少位?其寻址范围是多少? 20位,最大可寻址1MB空间 2. 8086 ...

最新文章

  1. PICRUSt2分析实战:16S扩增子OTU或ASV预测宏基因组EC、通路、KO(200806更新)
  2. KBMMW 4.80.00 发布
  3. 【神经网络与深度学习】读书笔记
  4. python 数据框缺失值_Python:处理数据框中的缺失值
  5. Linux Kettle 闪退问题解决方案
  6. Mac效率软件|HazeOver轻松虚化背景,专注当前任务窗口
  7. 宝马与intel合作 2021年推全自动无人驾驶车
  8. BOOST库介绍(六)——容器
  9. 内存卡linux系统格式化,SD卡无法格式化怎么办的解决方法
  10. AutoRunner 功能自动化测试项目实训之第二个实战案例(五)
  11. 安卓系统车牌离线识别,优秀的车牌识别算法
  12. Clouda框架开发留言板实例
  13. Google无限容量网盘
  14. 一、【s3c2440移植linux-3.5】移植准备
  15. Java反射--获取类方法的泛型返回或泛型参数
  16. 618营销新动向:Swisse年轻化产品教育成电商战场新突破口!
  17. GitHub 上排名前 100 的 Android 开源库介绍
  18. 分支定界法需要注意的是什么
  19. 分布式数据中心节点多?看托管云如何实现精细运维
  20. HDU 2033 - 人见人爱 A + B

热门文章

  1. Action Framework- Table PPFSFMLRU
  2. 德国同事Heiko开发的ABAP工具,能检测HANA数据库执行SQL的CPU time
  3. 使用cf push命令往CloudFoundry上部署应用的过程分析
  4. SAP S/4HANA生产排期scheduling profile配置
  5. SAP不同产品的UI开发策略概述
  6. SAP CRM Enterprise search后退按钮的实现
  7. 新装Ubuntu系统,窗口过大,无法拖动,按钮都点不到怎么办?
  8. 模拟电梯控制软件设计c语言,模拟电梯控制系统设计.docx
  9. densenet论文_DRCN论文解读
  10. 计算机网络技术超文本,网络协议确定了计算机网络传递和管理信息的规范,其中HTTP属于()A、超文本传输协议B、传输控制协...