C 表达式中的汇编指令

2020-01-18 19:38:31于海丽

asm 为 gcc 中的关键字,asm 表达式为在 C代码中嵌套汇编指令,该表达式只是单纯的替换出汇编代码,并不对汇编代码的含义进行解析。

asm 表达式有两种形式,第二种 asm-qualifiers 包含了 goto 语句。
第一种形式为常见的用法,AssemblerTemplate 和 OutputOperands 必须存在, 其中 Clobbers 存在需要 InputOperands 也出现。


asm asm-qualifiers ( AssemblerTemplate 
     : OutputOperands 
     [ : InputOperands
     [ : Clobbers ] ])

asm asm-qualifiers ( AssemblerTemplate 
      : 
      : InputOperands
      : Clobbers
      : GotoLabels)

Qualifiers 的类型

volatile, 避免编译器的优化inline, 内敛限定符,最小的体积goto, 包含跳转指令

参数

AssemblerTemplate
- 汇编指令模板是包含汇编器指令的文字字符串,编辑器替换引用输入,编译器不会解析该指令的含义。OutputOperands
- 由 AssemblerTemplate 中的指令修改的C变量的逗号分隔列表,允许使用空列表。InputOperands
- 由 AssemblerTemplate 中的指令读取的C变量的逗号分隔列表,允许使用空列表。Clobbers
- 用逗号分隔的寄存器列表或由 AssemblerTemplate 修改的值,不能出现在 OutputOperands 和 InputOperands 中被提及,允许使用空列表。GotoLabels
- 当使用asm的goto形式时,此部分包含 AssemblerTemplate 中的代码可能跳转到的所有C标签的列表。

AssemblerTemplate

汇编指令由一个字符串给出,多条汇编指令结合在一起使用的时候,中间以 rt 隔开,如


asm("inc %0ntinc %0" : "=r"(res) : "0"(res));

/APP
# 11 "asm.c" 1
  inc %rax
  inc %rax
# 0 "" 2
/NO_APPs

需要转义的字符:%, =, {, }, |

故在ATT汇编中,对寄存器进行操作的需要双 %%, 如 inc %%rax.

OutputOperands

操作数之间用逗号分隔。 每个操作数具有以下格式:


[ [asmSymbolicName] ] constraint (cvariablename)

asmSymbolicName
- 为操作数指定名称,格式为 %[name]
c // res = num asm("movq %[num], %[res]" : [res] "=r"(res) : [num] "m"(num));
- 如果未指定名称使用数字, 从 output 域开始,第一个参数为 %0, 一次类推, 这里的 res 为 %0, num 为 %1
c // res = num asm("movq %1, %0" : "=r"(res) : "m"(num));constraint
- 一个字符串常量,用于指定对操作数的存储的 约束, 需要以 "=" 或 "+" 开头cvariablename
- 指定一个C左值表达式来保存输出,通常是一个变量名。 括号是语法的必需部分

第一个参数为增加可读性使用的,现在我们有代码如下


int64_t res;
int64_t num = 1;

asm("movq %[num], %[res]" : [res] "=r"(res) : [num] "m"(num));
asm("movq %1, %0" : "=r"(res) : "m"(num));
asm("movq %1, %0" : "=m"(res) : "m"(num));
asm("movq %1, %0" : "=r"(res) : "r"(num));

// 对应的汇编代码, 只保留asm表达式中的代码
# 13 "asm.c" 1
  movq -16(%rbp), %rax // asm-1
 # 0 "" 2
/NO_APP

/APP
 # 15 "asm.c" 1
  movq -16(%rbp), %rax // asm-2
 # 0 "" 2
/NO_APP

/APP
 # 17 "asm.c" 1
  movq -16(%rbp), -8(%rbp) // asm-3
 # 0 "" 2
/NO_APP

/APP
 # 19 "asm.c" 1
  movq %rax, %rax // asm-4
 # 0 "" 2
/NO_APP