GCC内联汇编

详解内联汇编 有一些输出操作数在汇编代码中早早就被写入了新值A,在这之后,汇编代码才去读取某个输入操作数,这个输出操作数就被称为earlyclobber(早早就被改了)。所以,如果汇编代码中某个输出操作数是earlyclobber的,它的constraint就要加上“&”,这就是告诉编译器:给我分配一个单独的寄存器,别为了省事跟输入操作数用同一个寄存器。但是在C函数中写汇编代码,可以不用另外新建一个汇编文件,比较方便。第8行更新了%0的值后,第9行修改%1的值,由于%0、%1是同一个寄存器,所以%0的值也被修改了。 阅读详情

GCC内联汇编


1. 基本内联语法:

GCC用关键字asm表示一段用汇编语言写的源代码。形式如下:
asm ("assemble language");
说明:

  1. 汇编指令必须用双引号扩起来
  2. 如果有多条汇编指令,必须用换行符隔开\n,每条语句之前最好加上\t,为了区别汇编语言中的标号label。

编译器实际上把asm括号中双引号引起来的语句逐字的插入到编译后产生的汇编文件中.s,并进行了相应的替换操作。
可以这样:

asm ("movl $1,%eax\n\tmovl $0,%ebx\n\tint $0x80");

看起来麻烦,可以分行,分开成多个双引号:

asm ("movl $1,%eax\n\t"
    "movl $0,%ebx\n\t"
    "int $0x80");

可以使用C程序中的全局变量:

#include <stdio.h>

int a = 10;
int b = 20;
int result;

int main(){
    asm("pusha\n\t"
        "movl a, %eax\n\t"
        "movl b, %ebx\n\t"
        "imull %ebx, %eax\n\t"
        "movl %eax, result\n\t"
        "popa");
    printf("the answer is %d\n",result);
    return 0;
}

有时候编译器会对变易产生的汇编代码进行优化,可能导致产生的效果与我们预想的不一样。可以在asm之后使用volatile关键字进行说明,让编译器不进行优化。
Note:如果使用ANSI C标准,asm和volatile都要写成__asm__ __volatile__。

2. 扩展的ASM

基本形式有很多限制:输入输出只能使用C语言中的全局变量,而且不能随意地改变寄存器的值。(前面的例子中开头和结尾使用pusha和popa来保存寄存器)

扩展汇编形式:
asm (
	"assembly code"
	: output locations
	: input operands
	: changed registers);

这种形式有四个部分,用冒号隔开:

  • 汇编代码assembly code:内联汇编代码,语法同基本asm格式。变量用占位符表示。
  • 输出位置output locations:汇编代码中输出值所在的寄存器和内存单元列表。(执行汇编代码之后)
  • 输入操作符input operands:汇编代码中输入值所在的寄存器和内存单元的列表。(执行汇编代码前处理)
  • 改变的寄存器changed registers:内联汇编代码中改变的寄存器(用于提醒编译器对这些寄存器进行保护操作)。
操作符

在基本asm格式中,汇编语言中输入输出值可以直接使用C语言中的全局变量,但是在扩展asm格式中,格式不太一样:
"constraint"(variable)
variable是一个C语言变量(全局变量或局部变量都可以),constraint定义了从哪里取这个变量(对于输入变量来说)或往哪里存放(对输出变量)。constraint可能的取值如下表:

constraintdescription
ause the %eax,%ax or %al regiters
buse the %ebx,%bx or %bl registers
cuse the %ecx,%cx or %cl registers
duse the %edx,%dx or %dl registers
Suse the %esi or %si registers
Duse the %edi or %di registers
ruse any available general-purpose register
quse either the %eax,%ebx,%ecx or %edx register
Ause the %eax and the %edx regiters for a 64-bit value
fuse a floating-point register
tuse the first(top) floating-point register
uuse the second floating-point register
muse the variable’s memory location
ouse an offset memory location
Vuse a direct memory location
iuse an immediate integer value
nuse an immediate integer value with a known value
guse any register or memory location available

除了这些限制,输出值还包含一个限制修饰符,它指明编译器如何处理输出值。

output modiferdescription
+The operand can be both read from and written to
=The operand can only be written to
%The operand can be switched with the next operand if necessary
&The operand can be deleted and reused before the inline functions c

举例:

asm ("assembly code" : "=a"(result) : "d"(data1),"c"(data2));

这个例子中C变量data1放在%edx,data2放在%ecx。输出结果会被放到%eax,然后送到result变量。

#include <stdio.h>
int main(){
    int data1 = 10;
    int data2 = 20;
    int result;
    
    asm ("imull %%edx, %%ecx\n\t"
        "movl %%ecx, %%eax"
        : "=a"(result)
        : "d"(data1), "c"(data2)
        );
    printf("The result is %d\n",result);
    return 0;
}
asm volatile ("cld\n\t"
        "rep movsb"
        :
        :"S"(input),"D"(output),"c"(length));

由于没有指定输出规则,编译器会认为这段汇编是不必要的,因此要加上volatile。

占位符

汇编语言部分assembly language可以使用占位符placeholder用来引用输出输入变量。格式为%0 %1 ...用来表示输出输入列表中的变量。

asm ("imull %1, %2\n\t"
    "movl %2, %0\n\t"
    :"=r"(result)
    :"r"(data1),"r"(data2)
    );

%0代表存放result的寄存器;%1代表存放data1的寄存器;%2代表存放data2的寄存器。

asm ("imull %1,%0"
    : "=r"(data2)
    : "r"(data1),"0"(data2));

"0"表示让编译器使用第一个命名的寄存器。

int dividend = 20 ;
int divisor = 5;
int result ;
asm ("divb %2\n\t"
    "movl %%eax, %0"
    :  "=m"(result)
    : "a"(dividend),"m"(divisor));

内联汇编可以使用标签,用来进行跳转。数字可以作为局部标签。

asm ("cmp %1, %2\n\t"
    "jge 0f\n\t"
    "movl %1, %0\n\t"
    "jmp 1f\n"
    "0:\n\t"
    "movl %2, %0\n"
    "1:"
    :"=r"(result)
    :"r:(a),"r"(b));

0: 1:都是label,jmp 0f中f表示forward,如果向后跳转使用b即backward。

C语言内联汇编(详细)介绍附实例快速掌握 使用内联汇编主要目的是为了提高效率,同时还是为了实现 C 语言无法实现的部分。asm("汇编语句": 输出部分: 输入部分: 会被修改的部分);asmvolatile(“汇编语句”: 输出部分: 输入部分: 会被修改的部分);各部分使用“:”格开,汇编语句必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。第一部分是汇编语句,其中 “asm” 是内联汇编语句关键词。 阅读详情

相关推荐

C语言ASM(GCC Inline ASM)汇编内嵌语法

带有C/C++表达式的内联汇编GCC允许你通过C/C++表达式指定内联汇编中"Instrcuction List"中指令的输入和输出,你甚至可以不关心到底使用哪个寄存器被使用,完全靠GCC来安排和指定。这一点可以让程序员避免去考虑有限的寄存器的使用,也可以提高目标代码的效率。

qq_34272143的博客 7271

GCC-内联汇编

认识GCC内联汇编,读懂GCC内联汇编

m0_46929878的博客 1367

GCC 内联汇编语法

GCC 内联汇编语法

zhu_superman的博客 1482

GCC内联汇编及其在Linux内核中的使用

GCC内联汇编及其在Linux内核中的使用

ComputerInBook的专栏 1439

gcc 内联汇编用法介绍

前言大部分内容翻译提取自某国外HOW-TO文档,原地址: http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html AT&T汇编语法gcc内联汇编语法采用AT&T格式,主要不同有五个方面 1. 源操作数和目标操作数的位置与intel格式不同 2. 寄存器命名,AT&T在寄存器前加百分号(%) 3. 字面值前加美元符号($

jmp esp 5349

DPDK gcc内联汇编

dpdk 内联汇编

fengcai_ke的博客 505

GCC 内联汇编

How to Use Inline Assembly Language in C Code1 The asm keyword allows you to embed assembler instructions within C code. The asm keyword is a GNU extension. When writing code that can be compiled wit...

深空深蓝的博客 962

STK与Matlab连接报错?手把手教你解决mexConnect函数执行问题(附完整避坑指南)

本文针对STK与Matlab连接时常见的“mexConnect函数执行”报错,提供了完整的诊断与解决方案。文章深入剖析了错误根源在于路径冲突或文件损坏,并手把手指导用户通过定位STK连接器文件、正确配置Matlab路径(包括使用addpath命令)以及执行初始化测试三步走策略,彻底解决问题。同时附上版本兼容性检查、安装避坑指南及构建稳健工作流的建议,帮助用户建立可靠的STK-Matlab联合仿真环境。

yolo5detector的博客 472

GCC内联汇编基础

GCC内联汇编基础 (为了方便阅读,做成了pdf 格式,有目录: http://download.youkuaiyun.com/source/903658)     GCC内联汇编基础 Sandeep.S (原作者)v0.1, 01 March 2003.  翻译:fancylea 版权所有,禁止用作商业用途。 http://blog.youkuaiyun.com/fancylea

※旅程※ 1840

告别“单打独斗”:Oh My Open Code 如何用多模型协作重塑 AI 编程范式

介绍"Oh My OpenCode"——一个能协调多个专业AI模型完成复杂开发任务的智能编程框架。您将看到它如何分配任务、发挥不同模型的独特优势,并通过并行处理和实时纠错等功能解决AI编程流程中的常见痛点。

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 4213

扩增子分析|基于零模型的群落确定性和随机性构建过程——R实战

周集中教授团队多年在群落确定性和随机性过程深耕,于2017年总结出来下述图表中的计算路径,广受生态领域研究者的推崇。本文基于该计算路径,梳理了整理了邓晔老师组的代码,通过一个实例演示了计算过程和结果。

weixin_46814750的博客 4673

GCC内联汇编教程

 原文链接:https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html ,此文为我的中文翻译,转载请标明出处! GCC-Inline-Assembly-HOWTO Sandeep.S   本HOWTO解释了GCC提供的内联汇编功能的使用方法。阅读本文只有两个先决条件,是x86汇编语言和C的基本知识。   1. 简介 ...

lwx62的专栏 1万+

macOS向日葵闪退终极修复:权限设置与后台运行全解析

本文详细解析了macOS上向日葵远程控制软件闪退问题的根源与解决方案,重点介绍了权限设置与后台运行的优化方法。通过配置屏幕录制、辅助功能等关键权限,以及优化后台进程管理,有效解决闪退问题,提升远程控制软件的稳定性与使用体验。

fern8的博客 1765

riscv下的GCC内联汇编

GCC内联汇编 文章目录GCC内联汇编语法规则输入操作数与输出操作数可能影响的寄存器或存储器Example汇编中调用C/C++函数 语法规则 asm volatile( 汇编指令列表 ∶输出操作数 //非必需 ∶输入操作数 //非必需 ∶可能影响的寄存器或存储器 1/非必需 ); Explanation asm 是GCC的关键字,表示内联汇编操作,注 __asm__ 是GCC中asm的宏定义,也可以使用 volatile 或者 __volatile__ 是可选的,表示不进行任何优化,否则某些

m0_52050582的博客 6163

无线自组织网络基础知识

参考书籍:《无线自组织网络路由协议及应用》 目录第一章 绪论1.1 无线自组织网络概述1.1.1 无线自组织网络的定义及分类1.1.2无线自组织网络的主要特点1.1.3无线自组织网络的应用与发展1.无线自组织网络的应用2.无线自组织网络的起源和发展1.2典型的无线自组织网络1.2.1移动Ad Hoc网络1、移动Ad Hoc网络的定义2.移动AdHoc网络的特点3.移动Ad Hoc网络的应用1.2....

逸凌Time 2万+

灯塔问题:贪心与动态规划算法解析

区间覆盖问题是算法设计中的经典案例,常用于理解贪心算法与动态规划的核心差异。贪心算法通过局部最优选择逐步构建全局解,具有O(n log n)的高效时间复杂度,特别适合处理一维区间覆盖场景。动态规划则采用自底向上的填表法,虽然通用性更强但复杂度较高。在实际工程中,这类算法广泛应用于无线基站部署、监控设备布置等资源优化场景。通过分析灯塔问题的两种解法,可以深入掌握算法选择的关键因素,如问题规模、性能要求和实现复杂度。

weixin_28720573的博客 259

【转贴】GCC内联汇编基础

原文作者 Sandeep.S英文原文 [https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html] 本文将介绍GCC编译环境下,在C语言代码中嵌入汇编代码的基本方法。阅读本文需要您具备80X86汇编语言和C语言的基础知识。为了使中文描述更加清楚自然,翻译过程中加入了稍许解释和意译部分。 简介 版权/反馈/勘误/...

weixin_30443813的博客 424

C#调用Halcon程序三种方法

C#调用Halcon程序三种方法 1.halcon导出C#文件,在C#里面调用 2.在C#里面使用Halcon引擎调用Halcon程序 3.在C#里面使用Halcon引擎调用.hdev下本地函数或者.hdvp外部函数 Halcon引擎手册:C:/Program Files/MVTec/HALCON-21.11-Progress/doc_en_US/html/manuals/programmers_guide/programmers_guide_0120.html 1.导出C#(代码我只给出类,需要调用)

A541925504的博客 1万+

linux gcc 内联汇编入门

目录 2. 概览(Overview of the whole thing.) 3、GCC汇编语法(GCC Assembler Syntax.) 3.1. 源-目标顺序(Source-Destination Ordering) 3.2. 寄存次命名(Registry Naming) 3.3. 立即操作数(Immediate Operands) 3.4. 操作数大小(Operand Siz...

whatday的专栏 866

122、Android Camera HAL3 框架:Request、Result、Metadata 的异步管道模型

本文深入剖析了Android Camera HAL3框架中的异步管道模型,围绕Request、Result和Metadata三个核心要素展开。作者通过实际案例(黑屏闪退问题)切入,揭示了异步模型中常见的帧序错乱陷阱。文章详细阐释了三个角色的交互机制,指出HAL3采用生产者-消费者模式的关键特征:Request与Result一一对应但不保证顺序。针对开发实践,总结了三个必须加锁的场景和回调函数的锁使用禁忌,并给出解决帧序问题的具体方案(独立帧号生成器)。最后提出五项经验性建议,强调异步模型带来的灵活性与复杂性

sundong_81的博客 214

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

gcc 内联汇编

gcc 内联汇编 文章目录gcc 内联汇编前言一、GCC asm 声明小例子二、优化C代码三、MORE内嵌汇编作为预处理宏C 桩函数替换C变量的符号名替换C函数的符号名强制使用特定的寄存器临时使用寄存器寄存器的用途Common pitfalls 前言 gcc 内联汇编介绍,转载 https://blog.youkuaiyun.com/lhf_tiger/article/details/32343851 对于基于ARM的RISC处理器,GNU C编译器提供了在C代码中内嵌汇编的功能。这种非常酷的特性提供了C代码没有的

yanzhongqian的博客 961

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

arm下的gcc内联汇编

arm下的gcc内联汇编 __asm__ __volatile__内嵌汇编用法简述 在阅读C/C++原码时经常会遇到内联汇编的情况,下面简要介绍下__asm__ __volatile__内嵌汇编用法。 带有C/C++表达式的内联汇编格式为: __asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modif

格物致知 1865

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: 互斥:软件算法
下一篇: 重载new和delete
InvokerZhang
博客等级 码龄11年 9粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值