浅析GNU C嵌入汇编特性

前言

在C语言编程中,使用汇编指令有两种方式,一种是使用单独的汇编源文件,在最后编译的时候和其它C工程文件编译到一起,这种方式能够做到汇编函数和C函数的互相调用,但是如果希望在C语言中直接调用汇编表达式就不是那么方便了,为此我们需要使用另一种方式,即内嵌汇编。

GCC嵌入汇编语法

内嵌汇编使用一种约束好的格式来实现C调用汇编指令,GCC使用的嵌入汇编语法的基本格式如下所示

__asm__ (汇编指令模板
    :输出部分
    :输入部分
    :破坏描述部分);

上述格式给出了嵌入汇编时可能需要使用到的基本元素,依次为汇编指令模板、输出部分、输入部分和破坏描述部分,各部分使用”:”格开,其中汇编语句模板必不可少,其他三部分可选。如果使用了后面的部分,而前面部分为空,也需要用”:”格开,相应部分内容为空。示例如下:

__asm__ __volatile__("cli": : :"memory")

在GNU C嵌入汇编中,我们常看到__asm__后都会带上__volatile____volatile__表示编译器不要优化代码,后面的指令保留原样,volatile是它的别名。一个更加完整的嵌入汇编使用如下所示:

__asm__ __violate__ ("addl %1, %%eax;"
    "movl %%eax,%0;" 
    : "=r" (result) 
    : "r" (input));

汇编指令模板

汇编语句模板由汇编语句序列组成,语句之间使用”;”、”\n”或”\n\t”分开。指令中的操作数可以使用占位符引用C语言变量,操作数占位符最多10个,名称如下:%0,%1,…,%9,其中%0表示第一个参数,%1表示第二个参数。另外,为了增强代码可读性,可以使用汇编符号名字来替代以%表示的操作数。

__asm__ __violate__ ("addl %[in], %%eax;"
    "movl %%eax, %0;" 
    : [res] "=r" (result) 
    : [in]"r" (input));

其中,[res]表示定义了一个汇编符号操作数,符号名为res,对应于输出参数"=r" (result);同理,[in]对应于输入参数"r" (input)

转义字符

汇编指令模板规定了一些特殊字符的含义:

  • %%: 在输出的汇编代码中表示一个’%'字符,如上面的嵌入汇编示例中,%%eax等价于%eax,在AT&T的汇编语法中,引用寄存器需要加上%前缀;
  • %= 在输出的汇编代码中生成一个唯一的数字,该数字可以代表编写的内嵌汇编程序,这相当于生成了一个本地标号;

输出部分

输出部分描述输出操作数,不同的输出操作数之间用逗号格开,每个操作数由限制字符串和C语言变量组成。每个输出操作数的限制字符串通常以”=”或者“+”开头,然后是一个字母表示对操作数类型的说明,接着是关于变量结合的约束。“=”表示被修饰的操作只具有可写属性,“+”号表示被修饰的操作数具有可读可写属性。

__asm__ __volatile__("pushfl ; popl %0 ; cli":"=a" (x) )

上面的示例会使用eax寄存器存放pop出的值,然后存储到变量x中

输入部分

输入部分描述输入操作数,不同的操作数之间使用逗号格开,每个操作数描述符由限制字符串和C语言变量组成。输入部分描述的操作数只有只读属性,不允许修改,因此,在输入部分中,不能使用“=”或者“+”约束条件,否则编译器会报错。

__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));

破坏描述部分

破坏描述符用于通知编译器我们使用了哪些寄存器或内存,由逗号格开的字符串组成,每个字符串描述一种情况,一般是寄存器名;除寄存器外比较常用的还有“memory”和“cc”:

  • memory:告知GCC编译器,嵌入汇编代码修改了内存中的值,强迫编译器在执行该汇编代码前存储所有缓存的值,在执行完汇编代码之后重新加载该值,目的是防止编译乱序;
  • cc:表示嵌入汇编代码修改了状态寄存器的相关标志位。

限制字符串

限制字符的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系。限制字符有很多种。有些是与特定体系结构相关,此处列出常用的限定字符和x86中可能用到的一些常用的限定符。

限定符类型含义
“r”寄存器将变量放入通用寄存器中
“a”寄存器将变量放入eax寄存器中
“b”寄存器将变量放入ebx寄存器中
“c”寄存器将变量放入ecx寄存器中
“d”寄存器将变量放入edx寄存器中
“m”内存内存变量
“0-9”匹配逐一匹配操作数表达式,注意与%1-%9区分

示例分析

在这里插入图片描述

相关参考

  • 《奔跑吧,Linux内核》
  • 《GCC工具手册》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值