编程语言
首页 > 编程语言> > 内联汇编

内联汇编

作者:互联网

一、基本内联汇编

1.asm [volatile] ("汇编指令")

——所有汇编指令,必须用双引号包起来,超过一条指令必须用用 \n 进行分割,为了排版,需要加上 \t。比如说,下面是一张加 \t 和不加 \t 的对比图,可以看出加上 \t 后指令会对齐

  和 C 语言一样,加上 volatile 会告诉编译器不要优化内联汇编。

2.操作全局变量

  寄存器和内存之间可以互相交换数据,对于寄存器,必须要加 % 引用

二、扩展内联汇编

  全局变量有着自己的标签,可以被内联汇编识别出来,但是局部变量就不行了。为了解决这个问题,出现了扩展内联汇编格式

  asm [volatile] ("汇编指令" : "输出操作数列表" : "输入操作数列表" : "改动的寄存器"),其规则如下:

——输出操作数列表,将处理结果传递到 C 代码。

——输入操作数列表,将 C 代码的操作数传递给内联汇编。

——告诉编译器用了哪些寄存器。

——改动的寄存器可以忽略,但前两个冒号必须要有,即使其中一个什么也没有。

1.输入输出操作数列表

  告诉内联汇编代码,向哪些内存地址或寄存器读取/输出数据,这个过程需要满足一定的格式:

  "[输出修饰符]约束"(寄存器或内存地址)

1.约束

——a:使用 eax/ax/al 寄存器;

——b:使用 ebx/bx/bl 寄存器;

——c:使用 ecx/cx/cl 寄存器;

——d:使用 edx/dx/dl 寄存器;

——r:使用通用寄存器;

——m:使用内存地址。

2.输出修饰符

——+:表示被修饰的操作数可读可写;

——=:表示被修饰的操作数只能写入;

——%:表示被修饰的操作数可以和下一个操作数互换;

——&:内联函数完成前,可以重新使用或删除被修饰的操作数。

2.使用寄存器操作局部变量

  用 eax 修饰变量 a,用 ebx 修饰变量 b,用 ecx 修饰变量 sum,输入变量可以不加输出修饰符,但输出变量需要加 "="去修饰,同时扩展内联汇编需要加两个 %% 去修饰寄存器

3.声明改动的寄存器

  上一小节中,可以看到 gcc 使用了 edx 寄存器,现在来让 gcc 不使用这个寄存器:

 

三、使用占位符

  如果变量很多的话,寄存器不太够用,所以出现了占位符。

1.用占位符代替寄存器

  按照输入输出列表中的顺序,分别是 0,1,2......:

2.给寄存器起别名

  编号看起来还需要对比操作数列表,阅读体验感不佳,所以可以给他取个别名,这样一眼就可以看出是要进行 a + b 的操作,将结果赋给 sum:

3.直接操作内存

  其实和使用寄存器没啥区别,就是将修饰符改成 "m" 而已,但是由于指令不能直接操作两个内存,需要寄存器做中间变量:

标签:汇编,操作数,列表,寄存器,修饰,内联
来源: https://www.cnblogs.com/shuijiaoa/p/16060156.html