关于GCC内联汇编(也可以叫内嵌汇编)的简单学习
1、什么是内嵌汇编
内嵌汇编(Inline Assembly),是一种高级编程语言(C/C++)中常用的源码中直接嵌入汇编语言的技术,从而可以实现对底层硬件的直接控制或起到优化性能的作用。
1.1、内嵌汇编的特点
(1)直接控制:可以使用汇编语言直接控制CPU指令,进行更接近硬件级别的操作;
(2)性能优化:在某些关键代码中,使用汇编指令可以实现更高的执行效率,尤其是在要精细控制硬件相关资源时;
(3)与高级语言结合:允许在同一源文件中使用两种语言,实现汇编语言和高级语言的无缝融合;
1.2、使用内嵌汇编的场景
(1)性能敏感的代码
(2)需要直接控制相关硬件
(3)特定平台的优化;
1.3、使用内嵌汇编的缺点
(1)可移植性变差,因为与特定的硬件结果和编译器强相关,因此对代码移植性不友好;
(2)复杂性,通常编码中不会将汇编和高级语言写在一起,这样不太符合常规,对高级语言代码来说,会导致代码更复杂,可阅读性变差;
(3)代码调试更复杂;
2、内嵌汇编的相关写法介绍
(1)典型写法:
asm("汇编语句": 输出部分: 输入部分: 会被修改的部分);
共四个部分,其中汇编语句必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。
(2)常用写法
__asm__ __volatile__(" %0 = UTIMER " : "=r"(ret));
这行代码实际是GCC内联汇编的标准写法,()内是对应具体的汇编操作;
__asm__是GCC关键字asm的宏定义;#define __asm__ asm;
__asm__或asm用来声明一个内联汇编表达式,所以任何一个内联汇编表达式都是以它开头的,是必不可少的。
典型应用示例:
__asm__ __volatile__ ("Instruction List");
(3)内联汇编中%0,=r 是什么?
“%0”代表指令的操作数,称为占位符,内联汇编靠它们将C语言表达式与指令操作数相对应;
“ret”前面的限制字符串是“=r”,其中“=”表示“ret”是输出操作数,“r”表示需要将“ret”与某个通用寄存器相关联,先将操作数的值读入寄存器,然后在指令中使用相应寄存器,而不是“ret”本身,
当然指令执行完后需要将通用寄存器中的值存入变量“ret”,从表面上看好像是指令直接对“ret”进行操作,实际上GCC做了隐式处理;
所以下面这个内嵌汇编实现的操作如下:
CPU首先获取UTIMER的返回值,然后将此值存放到CPU的通用寄存器中,最后再将值从通用寄存器中取出并放到ret对应的地址中;
__asm__ __volatile__(" %0 = UTIMER " : "=r"(ret));
3、C语言中内嵌汇编代码示例
#include <stdio.h>
int main() {
int a = 2, b = 4, result;
// 使用内嵌汇编进行加法
asm ("addl %%ebx, %%eax;"
: "=a" (result) // 输出
: "a" (a), "b" (b) // 输入
);
printf("Result: %d\n", result);
return 0;
}
在这个示例中,asm关键字用于插入汇编代码,addl
指令用于将 b
加到 a
上,结果存储在 result
中。
4、参考文档
https://www.cnblogs.com/FireLife-Cheng/p/18186927
https://zhuanlan.zhihu.com/p/456311418