用C写程序比直接用汇编写程序更简洁,可读性更好,但效率可能不如汇编程序,因为C程序毕竟要经由编译器生成汇编代码,尽管现代编译器的优化已经做得很好了,但还是不如手写的汇编代码。另外,有些平台相关的指令必须手写,在C语言中没有等价的语法,因为C语言的语法和概念是对各种平台的抽象,而各种平台特有的一些东西就不会在C语言中出现了,例如x86是端口I/O,而C语言就没有这个概念,所以in/out指令必须用汇编来写。

C语言简洁易读,容易组织规模较大的代码,而汇编效率高,而且写一些特殊指令必须用汇编,为了把这两方面的好处都占全了,gcc提供了一种扩展语法可以在C代码中使用内联汇编(Inline Assembly)。最简单的格式是__asm__("assembly code");,例如__asm__("nop"); ,nop 这条指令什么都不做,只是让CPU空转一个指令执行周期。如果需要执行多条汇编指令,则应该用\n\t将各条指令分隔开,例如:

__asm__("movl $1, %eax\n\t"
"movl $4, %ebx\n\t"
"int $0x80");

通常 C 代码中的内联汇编需要和C的变量建立关联,需要用到完整的内联汇编格式:

__asm__(assembler template
: output operands /* optional */
: input operands /* optional */
: list of clobbered registers /* optional */
);

这种格式由四部分组成,第一部分是汇编指令,和上面的例子一样,第二部分和第三部分是约束条件,第二部分指示汇编指令的运算结果要输出到哪些C操作数中,C操作数应该是左值表达式,第三部分指示汇编指令需要从哪些C操作数获得输入,第四部分是在汇编指令中被修改过的寄存器列表,指示编译器哪些寄存器的值在执行这条__asm__语句时会改变。后三个部分都是可选的,如果有就填写,没有就空着只写个:号。例如:

例 19.6. 内联汇编

#include <stdio.h>

int main()
{
int a = 10, b; __asm__("movl %1, %%eax\n\t"
"movl %%eax, %0\n\t"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);
printf("Result: %d, %d\n", a, b);
return 0;
}

这个程序将变量a的值赋给b"r"(a)指示编译器分配一个寄存器保存变量a的值,作为汇编指令的输入,也就是指令中的%1(按照约束条件的顺序,b对应%0a对应1%),至于%1究竟代表哪个寄存器则由编译器自己决定。汇编指令首先把%1所代表的寄存器的值传给eax(为了和%1这种占位符区分,eax前面要求加两个%号),然后把eax的值再传给%0所代表的寄存器。"=r"(b)就表示把%0所代表的寄存器的值输出给变量b。在执行这两条指令的过程中,寄存器eax的值被改变了,所以把"%eax"写在第四部分,告诉编译器在执行这条__asm__语句时eax要被改写,所以在此期间不要用eax保存其它值。

我们看一下这个程序的反汇编结果:

        __asm__("movl %1, %%eax\n\t"
80483dc: 8b 55 f8 mov -0x8(%ebp),%edx
80483df: 89 d0 mov %edx,%eax
80483e1: 89 c2 mov %eax,%edx
80483e3: 89 55 f4 mov %edx,-0xc(%ebp)
"movl %%eax, %0\n\t"
:"=r"(b) /* output */
:"r"(a) /* input */
:"%eax" /* clobbered register */
);

可见%0%1都代表edx寄存器,首先把变量a(位于ebp-8的位置)的值传给edx然后执行内联汇编的两条指令,然后把edx的值传给b(位于ebp-12的位置)。

关于内联汇编就介绍这么多,本书不做深入讨论。

C内联汇编的更多相关文章

  1. x86平台转x64平台关于内联汇编不再支持的解决

    x86平台转x64平台关于内联汇编不再支持的解决     2011/08/25   把自己碰到的问题以及解决方法给记录下来,留着备用!   工具:VS2005  编译器:cl.exe(X86 C/C+ ...

  2. GNU C 内联汇编介绍

    GNU C 内联汇编介绍 简介 1.很早之前就听说 C 语言能够直接内嵌汇编指令.但是之前始终没有去详细了解过.最近由于某种需求,看到了相关的 C 语言代码.也就自然去简单的学习了一下如何在 C 代码 ...

  3. 最牛X的GCC 内联汇编

    导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 ...

  4. Linux 中 x86 的内联汇编

    工程中需要用到内联汇编,找到一篇不错的文章,趁机学习下. 原文地址:http://www.ibm.com/developerworks/cn/linux/sdk/assemble/inline/ 如果 ...

  5. GCC内联汇编入门

    原文为GCC-Inline-Assembly-HOWTO,在google上可以找到原文,欢迎指出翻译错误. 中文版说明 由于译者水平有限,故译文出错之处,还请见谅.C语言的关键字不译,一些单词或词组( ...

  6. C语言的本质(32)——C语言与汇编之C语言内联汇编

    用C写程序比直接用汇编写程序更简洁,可读性更好,但效率可能不如汇编程序,因为C程序毕竟要经由编译器生成汇编代码,尽管现代编译器的优化已经做得很好了,但还是不如手写的汇编代码.另外,有些平台相关的指令必 ...

  7. VC++的内联汇编

    1.移植性差,假设是软件项目建议不要用.假设希望一段程序仅在单一设备上执行而且效率极高,能够使用内联汇编. 比方.单片机开发. 2. ......持续更新中. .... .

  8. [翻译] GCC 内联汇编 HOWTO

    目录 GCC 内联汇编 HOWTO 原文链接与说明 1. 简介 1.1 版权许可 1.2 反馈校正 1.3 致谢 2. 概览 3. GCC 汇编语法 4. 基本内联 5. 扩展汇编 5.1 汇编程序模 ...

  9. vs编写x64内联汇编

    参考自: https://www.cnblogs.com/achillis/p/5369658.html 先转过来, 等实践过了再做相应的修改, hehe 编写涉及系统特性的一些底层程序,特别是She ...

随机推荐

  1. 9 本免费的 Python 语言编程书籍(转载)

    9 本免费的 Python 语言编程书籍 原文地址:http://linuxtoy.org/archives/9-free-python-books.html 2010-03-03 Toy Poste ...

  2. Python核心编程--学习笔记--7--字典和集合

    本章介绍Python语言中的映射类型(字典)和集合类型,包括操作符.工厂函数.内建函数与方法. 1 字典 字典是Python中唯一的映射类型——键key直接映射到值value.字典是容器类型,其对象是 ...

  3. Ruby处理二进制(未完成)

    https://practicingruby.com/articles/binary-file-formats http://stackoverflow.com/questions/16821435/ ...

  4. 苏泊尔借助微软CRM提升客户满意度

    企业背景 作为中国最大.全球第二的炊具研发制造商和中国小家电领先品牌,品质和创新一是苏泊尔矢志追求的企业理念,从火红点无油烟锅的发明到能做柴火饭的球釜IH饭煲的面世,苏泊尔用产品的创新和品质的承诺,不 ...

  5. Android-----第三方 ImageLoader 的简单配置和使用

    ImageLoader 的简单使用配置,最好是将配置信息放到application里面,这样我们就不需要每次使用都需要配置了 1.首先我们得有一个包 2.简单的配置信息 //显示图片的配置 Displ ...

  6. WCF 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性

    我出现这个问题主要是服务器返回数据量过大引起了,需要客户端服务端都要进行配置:我会说其实有神器的么....(工具=>wcf服务配置编辑器),用工具编辑下,就会完全搞定这个问题,再也不用纠结了 服 ...

  7. [shell基础]——sed命令

    关于sed sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓 ...

  8. 【每日scrum】NO.7

    Yesterday:学习和设计路线的编程 Today:编写代码 Problem:.在设计查询参观路线的时候,整个逻辑特别的混乱,设想了各种树,图以及网的遍历问题,但经过多次与同学的交流以及网上的查询资 ...

  9. windows和linux环境下制作U盘启动盘

    新笔记本上,要装xp的系统,100%会破坏原有的Linux系统,因为安装xp的时候会自动覆盖硬盘的主引导扇区,这个扇区一旦被重写,那么原有的linux根本就启动不了. 要想玩linux和xp双系统,一 ...

  10. "Mac OS X"想要进行更改。键入管理员的名称和密码以允许执行此操作("Mac OS X"想使用系统钥匙串)

    不知什么时候开始,每次我在运行xcode在真机上,或者archive打包的时间,都会弹出输入用户名和密码的框,搞的烦死了: 解决方法: 打开钥匙串访问 双击那些密钥弹出框: 改变到允许所有应用程序访问 ...