C程序代码中内嵌as汇编(一、基础知识)

来源:互联网 发布:淘宝关闭蚂蚁花呗支付 编辑:程序博客网 时间:2024/05/16 08:10

        汇编代码是最接近机器码,所以也是执行效率最高的,在操作系统中有将近10%的关键性代码是由汇编编写的,而还有部分代码是由C代码嵌入汇编构成的。C代码中嵌入汇编可以提高程序的执行效率,同时这种程序还既有高级语言的特性,可以灵活的和其他模块进行配合工作;

        c程序内嵌as汇编有比较多的规则,可以从最简单、最基本的开始学起直到后面学习现在通用的内嵌方式。

 #include<stdio.h>  int a = 10;  int b = 20;  int result;  int main(void) {     asm(         "pusha \n\t"                  "movl a, %eax\n\t"         "movl b, %ebx\n\t"         "imull %ebx, %eax\n\t"         "movl %eax, result\n\t"         "popa"         );       printf("the answord is :%d\n", result);     return 0; }
        上面就是基础的C代码中内嵌as汇编,有几个规则说明下:

        1、由关键字asm开始(好像所有的内嵌汇编都是由这个关键字开始的),汇编代码被包含在()内,全部内嵌汇编作为C代码的一条语句;

        2、这个是基础的内嵌汇编,只能使用全局变量,而不能使用局部变量,所以例题中变量都为全局的;

        3、C代码中的全局变量的值在汇编中被用作内存地址,所以可以直接使用变量名:movl a,  %eax;

        4、在汇编中每一条语句是要分开的,可以直接换行符也可以用分号(这里用\n来分割不同指令,\t不是必须的,只是为了代码对齐设置的),一点要把每一行语句放在双引号“”内;

        5、记住一定要在汇编开始时执行pusha(把所有通用寄存器全部压栈)和在结束时执行popa,这样做是为了防止内嵌汇编程序破坏掉C代码编译成的汇编程序;

        上面的例题中还可以用 volatile来修饰:asm volatile("assembly code");其实我想大家还是看这种内嵌方式看得比较多:__asm__,这是ANSI c的内嵌汇编方式,用__asm__替代了asm;


         ××××××××××××××××××××××××××××××××××××C程序中嵌入汇编扩展×××××××××××××××××××××××××××××××××××××××××

        上面的例题只是基础的内嵌汇编方式,因为想也可以想得到在嵌入的汇编中只能用全局变量,那嵌入汇编还有什么意义呢?下面看下嵌入汇编扩展,可以使用局部变量:

#include<stdio.h> int main(void) {     int data1 = 10;      int data2 = 20;      int result;     asm(         "imull %%ebx, %%eax\n\t"         "movl %%eax, %%edx\n\t"         :"=d"(result)         :"a"(data1),"b"(data2)        );       printf("the answord is :%d\n", result);     return 0; }
        我想如果是刚学嵌入汇编,上面的例题应该是没怎么看的懂的(至少我开始是没怎么看得懂的)。先来看看这个扩展后的汇编格式:

asm("assembly code":输出位置:输入位置:改变的寄存器);
        简单分析下:这里没有改变的寄存器列表,所以可以省略。

        先来看输入位置 :"a"(data1), "b"(data2),表示的意思是把data1传送到eax中,data2传送到ebx中(至于具体的哪个值对应哪个寄存器,随后会附上一张约束表);

        接着让ebx和eax相乘得到结果放在eax中,最后把eax中的结果传送给edx(这是一般的汇编语句,很容易的,为什么两个%,后面会解释);

        这时候可以看下输出位置  :"=d"(result),表示返回结果从edx中传送给result变量中。

       下面来说下扩展后的嵌入汇编的规则:

        1、具体的输入输出位置格式  :"汇编寄存器"(c程序变量),当然这里的汇编寄存器其实并不是eax之类的,而是一种约束(其实就是代替寄存器,可以查看约束表)比如:"a"(data1)  代表的就是汇编中的%eax和c代码中的变量data1相对应;

        2、可以使用全局变量和局部变量;若没有输出数据,输出位置可以空着,但需要有冒号。若改变寄存器列表没有,则可以什么都不写;

        3、寄存器要用%%寄存器(%%eax)表示,看了很多解释为什么会有两个%,有的人说是前一个%当作转义字符,我感觉是为了区分%1(表示第二个寄存器,后面会分析到)。

         约束代码表:
   
        输出修饰符列表:

    
        上图皆来至于 <<Professional Assembly Language>>

        转载请注明作者和原文出处,原文地址:http://blog.csdn.net/yuzhihui_no1/article/details/42709871

1 0