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

        汇编代码是最接近机器码,所以也是执行效率最高的,在操作系统中有将近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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值