内联汇编
作者:互联网
一、基本内联汇编
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