gcc内嵌汇编

恩,首先说明本文仅针对gcc。其他编译器请无视本文。

有时候我们希望在C/C++代码中使用嵌入式汇编,因为C中没有对应的函数或语法可用。比如我最近在ARM上写FIR程序时,需要对最后的结果进行饱和处理,但gcc没有提供ssat这样的函数,于是不得不在C代码中嵌入汇编指令。

1. 入门

在C中嵌入汇编的最大问题是如何将C语言变量与指令操作数相关联。当然,gcc都帮我们想好了。下面是是一个简单例子。

asm(“fsinx %1, %0”:”=f”(result):”f”(angle));

这里我们不需要关注fsinx指令是干啥的;只需要知道这条指令需要两个浮点寄存器作为操作数。作为专职处理C语言的gcc编译器,它是没办法知道fsinx这条汇编指令需要什么样的操作数的,这就要求程序猿告知gcc,方法就是指令后面的”=f”和”f”,表示这是两个浮点寄存器操作数。这被称为操作数规则(constraint)。规则前面加上”=”表示这是一个输出操作数,否则是输入操作数。constraint后面括号内的是与该寄存器关联的变量。这样gcc就知道如何将这条嵌入式汇编语句转成实际的汇编指令了:

fsinx:汇编指令名

%1, %0:和汇编指令对应的操作数

“=f”(result):操作数%0是一个浮点寄存器,与变量result关联(“关联”的意思就是说gcc执行完这条汇编指令后会把寄存器%0的内容送到变量result中)

“f”(angle):操作数%1是一个浮点寄存器,与变量angle关联(“关联”的意思是就是说gcc执行这条汇编指令前会先将变量angle的值读取到寄存器%1中)

因此这条嵌入式汇编会转换为至少三条汇编指令(非优化):

1> 将angle变量的值加载到寄存器%1

2> fsinx汇编指令,源寄存器%1,目标寄存器%0

3> 将寄存器%0的值存储到变量result

当然,在高优化级别下上面的叙述可能不适用;比如源操作数可能本来就已经在某个浮点寄存器中了。

这里我们也看到constraint前加”=”符号的意义:gcc需要知道这个操作数是在执行嵌入汇编前从变量加载到寄存器,还是在执行后从寄存器存储到变量中。

常用的constraints有以下几个(更多细节参见gcc手册):

m    内存操作数

r    寄存器操作数

i    立即数操作数(整数)

f    浮点寄存器操作数

F   立即数操作数(浮点)

从这个栗子也可以看出嵌入式汇编的基本格式:

asm(“汇编指令”:”=输出操作数规则”(关联变量):”输入操作数规则”(关联变量));

输出操作数必须为左值;这个显然。

2. 多个输入/输出操作数,或没有输出操作数

如果某个指令有多个输入/输出操作数怎么办?例如arm有很多指令是三操作数指令。这个时候用逗号分隔多个规则:

asm(“add %0, %1, %2”:”=r”(sum):”r”(a), “r”(b));

每条操作数规则按顺序对应操作数%0, %1, %2。

对于没有输出操作数的情况,在汇编指令后就没有输出规则,于是就出现两个连续冒号,后跟输入规则。

时间: 2024-12-21 21:44:05

gcc内嵌汇编的相关文章

AT&T汇编语言与GCC内嵌汇编,Linux内核数据结构之链表

最近在看<Linux内核源代码情景分析>,作者毛德操.书中刚开始介绍了AT&T汇编语言与GCC内嵌汇编,以及Linux内核数据结构之链表.可惜书中介绍的不够全面.因为推荐大家阅读下面两篇文章.很不错. AT&T汇编语言与GCC内嵌汇编:http://grid.hust.edu.cn/zyshao/Teaching_Material/OSEngineering/Chapter2.pdf. Linux内核数据结构之链表:http://www.cnblogs.com/Anker/p/

GCC在C语言中内嵌汇编 asm __volatile__ 【转】

转自:http://blog.csdn.net/pbymw8iwm/article/details/8227839 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作. 1.简单的内嵌汇编 例: __asm__ __volatile__("hlt"); "__asm__"表示后面的

GCC内嵌AT&amp;T汇编语法

一 基本语法 1 寄存器引用 引用寄存器要在寄存器号前加百分号%,如"movl %eax, %ebx". 80386有如下寄存器: 1.8个32-bit寄存器 %eax,%ebx,%ecx,%edx,%edi,%esi,%ebp,%esp: 2.8个16-bit寄存器,它们事实上是上面8个32-bit寄存器的低16位:%ax,%bx,%cx,%dx,%di,%si,%bp,%sp: 3.8个8-bit寄存器:%ah,%al,%bh,%bl,%ch,%cl,%dh,%dl.它们事实上是寄

GCC在C语言中内嵌汇编 asm __volatile__

转自 http://blog.csdn.net/pbymw8iwm/article/details/8227839 在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作. 1.简单的内嵌汇编例: __asm__ __volatile__("hlt"); "__asm__"表示后面的代

内核bug.h以及GCC内联汇编的学习

所有的学习的内容都在注释当中,我的学习过程是,看到这个代码段之后,将其中需要的只是去大体的学习一遍.争取能够做到理解整体的部分. 下面展示出我的学习的代码: #ifndef _I386_BUG_H #define _I386_BUG_H /* * Tell the user there is some problem. * 告诉用户出现了一些问题 * The offending file and line are encoded after the "officially * undefined

内嵌汇编

static inline void arch_spin_lock(arch_spinlock_t *lock) {     unsigned long tmp; __asm__ __volatile__( "1: ldrex   %0, [%1]\n"           "   teq %0, #0\n"                         WFE("ne") "   strexeq %0, %2, [%1]\n&quo

最牛X的GCC 内联汇编

导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 汇编语言和 C 语言的基本认识. 1. 简介 1.1 版权许可 Copyright (C) 2003 Sandeep S. 本文档自由共享:你可以重新发布它,并且/或者在遵循自由软件基金会发布的 GNU 通用公共许可证下修改它:也可以是该许可证的版本 2 或者(按照你的需求)更晚的版本. 发布这篇文

操作系统学习之GCC内联汇编

GCC内联汇编(INLINE ASSEMBLY) 什么是内联汇编(Inline assembly)? 1.这是GCC对C语言的扩张,就是在C代码里面去写汇编代码 2.可以直接在C的语句中插入汇编指令 有何用处? 1.C语言不足以完成所有CPU的指令, 特别是有一些特权指令,比如加载gdt表(Global Descriptor Table 全局描述符表),从而使用汇编代码来完成 2.用汇编在C语言中手动优化,特别是在操作系统当中,使用汇编对操作系统的掌控更为精准,更加准确. 如何工作? 1.用给定

arm 内嵌汇编

内嵌汇编代码,每一个input和output operand,由被方括号[]中的符号名,限制字符串,圆括号中的C表达式构成 // example static inline void __down_write(struct rw_semaphore *sem) {     long oldcount; #ifndef    CONFIG_SMP     oldcount = sem->count;     sem->count += RWSEM_ACTIVE_WRITE_BIAS; #else