aarch64体系结构与编程4--GCC内嵌汇编
jason--liu opened this issue · 0 comments
jason--liu commented
GCC内嵌汇编
- 内嵌汇编(Inline Assembly Language):在C语言中嵌入汇编代码
- 目的:
- 优化:对于特定重要代码(time-sensitive)进行优化
- C语言需要访问某些特殊指令来实现特殊功能比如 内存屏障指令
内嵌汇编两种模式
- 基础内嵌汇编(Base Asm):不带参数
- 扩展的内嵌汇编(Extended Asm):C语言变量参数
基础内嵌汇编
asm asm-qualifiers ( AssemblerInstructions )
格式:
- asm关键字:表明这是一个GNU扩展
- 修饰词(qualifiers)
- volatile:在基础内嵌汇编中通常不需要这个修饰词
- inline:内联,asm汇编的代码会尽可能小
汇编代码块: - GCC编译器把内嵌汇编当成一个字符串
- GCC编译器不会去解析和分析内嵌汇编。
- 多条汇编指令,需要使用“\n\t”来换行
- GCC的优化器,可以移动汇编指令的前后位置。如果你需要保存汇编指令的顺序,最好使用多个内嵌汇编的方式。
扩展内联汇编
- asm关键字:表明这是一个GNU扩展
- 修饰词(qualifiers)
- volatile:用来关闭GCC优化
- inline:内联,asm汇编的代码会尽可能小
- goto:在内嵌汇编里会跳转到C语言的标签里
- 输出部:用于描述在指令部中可以被修改的C语言变量以及约束条件
- 输出部:用于描述在指令部中可以被修改的C语言变量以及约束条件
- 每个输出约束(constraint)通常以“=”号开头,接着的字母表示对操作数类型的说明,然后是关于变量结合的约束。
“=/+” + 约束修饰符 + 变量 - 输出部通常使用“=”或者“+”作为输出约束,其中“=”表示被修饰的操作数只具有可写属性,“+” 表示被修饰的操作数只具有可读可写属性。
- 输出部可以是空的
- 每个输出约束(constraint)通常以“=”号开头,接着的字母表示对操作数类型的说明,然后是关于变量结合的约束。
- 输入部:用来描述在指令部只能被读取访问的C语言变量以及约束条件
- 输入部描述的参数是只有只读属性,不要试图去修改输入部的参数的内容,因为GCC编译器假定,输入部的参数的内容在内嵌汇编之前和之后都是一致的
- 在输入部中不能使用“=”或者“+”约束条件,否则编译器会报错
- 输入部可以是空的。
- 破坏部(Clobbers)
- “memory”告诉GCC编译器内联汇编指令改变了内存中的值,强迫编译器在执行该汇编代码前存储所有缓存的值,在执行完汇编代码之后重新加载该值,目的是防止编译乱序。
- “cc”表示内嵌汇编代码修改了状态寄存器相关的标志位。
- 指令部中的 参数表示:
在内嵌汇编代码中,使用%0 对应输出部和输入部的第一个参数,使用%1表示第二个参数。
输出部和输入部的约束修饰符
输出部和输入部的约束修饰符 – 通用
- m:内存变量
- o:操作数为内存变量,但是其寻址方式是偏移量类型
- V:操作数为内存变量,但寻址方式不是偏移量类型
- r:通用寄存器
- i:立即数
- n:立即数
- p:操作数是一个合法的内存地址(指针)
输出部和输入部的约束修饰符 – ARM64
汇编符号名字来替代以前缀%
为了提高代码可读性,可以使用汇编符号名字来替代以前缀%来表示的操作数
内嵌汇编的高级用法 :和宏结合
技巧1: 使用了C语言的“#”运算符。在带参数的宏中,“#”运算符作为一个预处理运算符,可以把记号转换成字符串