GCC内嵌汇编语言
Inline Assembly language in C Code
GCC
提供了两种形式的内联汇编语句。- 基本
asm
语句,没有操作数 - 扩展
asm
语句,有一个或多个操作数
- 基本
基本ASM语句
扩展ASM语句
是带有C表达式形式的操作数的汇编指令。使用扩展语句可以在汇编程序中读取和修改C程序中的变量,还可以实现从汇编程序到C程序的跳转操作。
语法格式
1 | asm asm-qualifiers(AssemblerTemplate:OutputOperands[:InputOperands[:Clobbers]]) |
1 | asm asm-qualifiers(AssemblerTemplate:OutputOperands:InputOperands:Clobbers:GotoLabels) |
限定符——qualifiers
volatile
:禁止编译器对代码进行优化,以免产生意想不到的错误inline
:goto
:
汇编器模板——AssemblerTemplate
由指向输入、输出和跳转参数的标记和固定文本组合成的包含着汇编指令的字符串。编译器进行处理时,将用输入、输出和跳转参数替换相应的标记,然后生成最终的汇编指令。在此过程中,编译器不会对汇编指令进行解析。
可以在一个模板串中写入多条汇编指令,中间使用换行符分割\n\t
,但是多个指令执行时可能会偏离预期,此时可将其分割为单个汇编指令。
一些标记在此串中有特殊含义:
%%
:由编译器转换为%
%=
:产生一个和已有%{、%|、%}
:由编译器转换为{、|、}
输出参数——Output Operands
-
指出汇编指令将要修改的C语言中的变量,并设置相应的属性
-
语法格式
-
多个输出参数使用逗号
,
进行分隔 -
单个参数的格式如下:
1
[[asmSymbolicName]] constraint (cvarialblename)
-
-
参数说明
asmSymbolicName
:用于指定C语言中的变量在汇编中的名称。指定之后在汇编中可以使用%[Name]
来使用此变量的值。不指定时,在汇编中程序中可以使用%x
来使用相应的变量,其中x
是相应变量在参数列表中的相对位置,从0
开始编号。constraint
:用于指定对应的C程序中的变量在汇编程序中的存储位置及操作方式。格式为前缀约束符 附加约束符
- 前缀约束符:指出汇编指令对变量的操作
+
:表示此操作数对应的C变量会被汇编指令读和写。此时此操作数即是输入也是输出操作数。=
:表示此操作数对应的C变量会被汇编指令重写,只写。
- 附加约束符:指出相应的C变量在汇编程序中允许的存储位置。如果指定了多个,则编译器会选择最高效的一个。
m
:存在内存单元中r
:存在寄存器中
- 前缀约束符:指出汇编指令对变量的操作
cvariablename
:汇编指令中要修改的C程序变量名,必须是左值
1
输入参数——Input Operands
-
语法格式
-
多个输入参数使用逗号
,
隔开 -
单个参数的语法格式如下
1
[[asmSymbolicName]] constraint (cexpression)
-
-
参数说明
asmSymbolicName
:同输出参数constraint
:基本同输出参数,不以前缀约束符开头。有如下特殊情况- 数字:表示此输入参数和输出列表中数字索引处的输出参数具有相同的存储位置。用于没有指定
asmSymbolicName
的情况 - 名字:用于指定
asmSymbolicName
的情况,格式为[name]
- 数字:表示此输入参数和输出列表中数字索引处的输出参数具有相同的存储位置。用于没有指定
cexpression
:传递给汇编程序作为输入的C程序变量或者表达式
机器相关限定符
不同的体系结构定义了不同的限定符,对于x86
架构,有如下常用限定符
a
:a寄存器b
:b寄存器c
:c寄存器d
:d寄存器S
:SI
寄存器D
:DI
寄存器