asm

在C++里面使用内联汇编语法

非常的简单

Posted by 叉叉敌 on August 4, 2022

学习过程中的总结,有什么不对的地方望指出,谢谢~

Asm 语句允许直接在 C 代码中包含汇编指令。特别是对于代码的性能,或者访问 C 程序不易获得的汇编指令,这可以帮助我们最大限度地提高时间时间.

来看看下面的C代码,汇编语法一般情况下,第一个操作数是dst,就是下面我们看到的%1,是输出,%0是输入,也是source.

下面代码的意思就是:把src拷贝给dst,然后给dst加1. 所以如果你的cpu或者GPU支持这个指令,打印出来的结果就是2.

int src = 1;
int dst;   

asm ("mov %1, %0\n"
    "add $1, %0"
    : "=r" (dst) 
    : "r" (src));

printf("%d\n", dst);

上面这个实例里面的r的意思是register寄存器的意思,除了r还有其他关键字

  • r 操作数指定一个通用的寄存器 register
  • m 操作数指定一个内存地址 memory
  • i 操作数指定一个整数常量 integer
  • g 操作数必须是通用寄存器、内存地址或整数常量中的一个.也可以用rmi来表示

需要注意有简单的几点,可以下面的一个格式:

  • 扩展的 asm 语句必须位于函数内部。只有基本的空间可以是函数之外的。
  • 用 asm 关键字作为开头,也可以用__asm__,用前者的时候比较多
  • optional stuff可以为空、volatile、goto其中一个
  • assembler template 就是你想用的汇编指令
  • 每一个asm块,长度不超过30个inputs
  • 输出、输入、lable都是可选的
  • 冒号只需要到您希望使用的参数为止,如果希望跳过参数,则冒号之间没有任何内容是有效的

语法格式:

asm <optional stuff> (
	    "assembler template"
	    : outputs
	    : inputs
	    : clobbers
	    : labels)

输入和输出

输出和输入是汇编程序模板“格式字符串”的参数。它们是以逗号分隔的。他们都使用以下两种模式中的一种:

       "constraint" (expression)
[Name] "constraint" (expression)

限制

比如这个乘法指令imul %0, %1, %2,按照上面提到的%0是dst,后面2个是src.

对于x86指令架构,乘法指令有三个操作数的时候:此种形式需要一个目标操作数%0(第一个操作数)与两个源操作数(第二个与第三个操作数)。这里,第一个源操作数%1(可以是通用寄存器或内存位置)乘以第二个源操作数%2(立即数)。乘积随后存储到目标操作数%0(通用寄存器)。

  • 第一个%0 一定就是寄存器,不能是const
  • 第二个操作数%1,可能是regist或者是memory地址
  • 第三个操作数%2,一定就是const integer

(ARM 只支持寄存器上的运算,所以所有的操作数都是寄存器操作数。)

输出

输出指定左值,结果应该存储在操作结束的位置。可赋值的通常是 lvalue (变量、取消引用的指针、数组下标、结构字段等)。只要遵守约束,大多数左值都被接受为操作数: 例如,可以使用 r (register)传递位字段,但不能使用 m (memory) ,因为不能获取位字段的地址。

  • 输出的约束字符串必须以 = 或 + 作为前缀
  • + 表示输出实际上是一个读写值。操作数最初具有表达式包含的值。可以在程序集字符串中的任何位置读取此输出操作数。
  • =& 意味着输出是一个提前完成的输出。它的初始值未指定。一旦给 =& 操作数赋值,就不会出现从该操作数读取的错误。
  • = 意味着输出是只写的。
  • =@ccCOND= 的特殊情况,它允许您在汇编语句的末尾查询条件代码的结果。不能在程序集模板中引用条件输出。

比如x86指令集是这样的

asm("addl %1, %0" : "+rm" (foo) : "g" (bar))

在arm就是下面这样的,arm只有寄存器

asm("add %0, %1, %2" : "=r" (foo) : "r" (foo), "r" (bar))

输入

输入可以是任何值,只要它对约束有意义。例如,要使用 i 约束,编译器必须能够发现该值是一个常量。它们没有任何前缀。

如果语法中使用了asm volatile,代码有可能被优化掉,比如没有用到的无效语句.

还有其他的goto、labels等高级用法,可以在实战用多练习,这样更容易掌握,学习的新的只是用起来才是关键.

Read more

https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

https://llvm.org/docs/LangRef.html#inline-assembler-expressions

https://www.felixcloutier.com/documents/gcc-asm.html

github博客

微信公众号:cdtfug, 欢迎关注一起吹牛逼,也可以加微信号「xiaorik」朋友圈围观。