Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

Linux调试私房菜(四)揭开链接器的面纱、汇编语言的内嵌编程 源文件被编译后生成目标文件,这些目标文件如何生存最终的可执行程序?链接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。main()函数是第一个被调用执行的函数吗?链接选项-nostartfiles的意义是什么?链接时不要使用标准的系统启动文件。标准的系统库通常使用,除非使用-nostdlib或-nodefaultlibs。链接器根据什么原则完成具体的工作?在Linux中,进程代码段(.text)的合法起始地址为[0x08048000,0x08049000]8-1.lds8- 阅读详情
在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly。本文的笔记试图说明Inline Assembly的基本语法规则和用法。

内联汇编(或称嵌入汇编)的基本语法模板比较简单,如下所示(为使结构更清晰,这里特意做了换行,其实完全可以全部写到单行中):

asm [ volatile ] (
assembler template
[ : output operands ] /* optional */
[ : input operands ] /* optional */
[ : list of clobbered registers ] /* optional */

);


由代码模板可以看到,基本语法规则由5部分组成,下面分别进行说明。
1)关键字asm和volatile
asm为gcc关键字,表示接下来要嵌入汇编代码。为避免keyword asm与程序中其它部分产生命名冲突,gcc还支持__asm__关字,与asm的作用等价。
volatile为可选关键字,表示不需要gcc对下面的汇编代码做任何优化。同样出于避免命名冲突的原因,__volatile__也是gcc支持的与volatile等效的关键字。

2)assembler template
这部分即我们要嵌入的汇编命令,由于我们是在C语言中内联汇编代码,故需用双引号""将命令括起来,以便gcc以字符串形式将这些命令传给汇编器AS。例如可以写成这样:"movl %eax, %ebx"
有时候,汇编命令可能有多个,则通常分多行写,每行的命令都用双引号括起来,命令后紧跟"\n\t"之类的分隔符(当然,也可以只用1对双引号将多行命令括起来,从语法来说,两种写法均有效,我们可自行决定用哪种格式来写)。示例代码如下所示:
__asm__ __volatile__ ( "movl %eax, %ebx\n\t"
"movl %ecx, 2(%edx, %ebx, $8)\n\t"
"movb %ah, (%ebx)"
);
还有时候,根据程序上下文,嵌入的汇编代码中可能会出现一些类似于魔数(Magic Number )的操作数,比如下面的代码:
int a=10, b;
asm ("movl %1, %%eax; /* NOTICE: 下面会说明此处用%%eax引用寄存器eax的原因
movl %%eax, %0;"
:"=r"(b) /* output 该字段的语法后面会详细说明,此处可无视,下同 */
:"r"(a) /* input */
:"%eax" /* clobbered register */

);


我们看到,movl指令的操作数(operand)中,出现了%1、%0,这往往让新手摸不着头脑。其实只要知道下面的规则就不会产生疑惑了:在内联汇编中,操作数通常用数字来引用,具体的编号规则为:若命令共涉及n个操作数,则第1个输出操作数(the first output operand)被编号为0,第2个output operand编号为1,依次类推,最后1个输入操作数(the last input operand)则被编号为n-1。
具体到上面的示例代码中,根据上下文,涉及到2个操作数变量a、b,这段汇编代码的作用是将a的值赋给b,可见,
a是input operand,而b是output operand,那么根据操作数的引用规则,不难推出,a应该用%1来引用,b应该用%0来
引用。
还需要说明的是:当命令中同时出现寄存器和以%num来引用的操作数时,会以%%reg来引用寄存器(如上例中的%%eax),以便帮助gcc来区分寄存器和由C语言提供的操作数。


3)output operands
该字段为可选项,用以指明输出操作数,典型的格式为:
: "=a" (out_var)
其中,"=a"指定output operand的应遵守的约束(constraint),out_var为存放指令结果的变量,通常是个C语言变量。本例中,“=”是output operand字段特有的约束,表示该操作数是只写的(write-only);“a”表示先将命令执行结果输出至%eax,然后再由寄存器%eax更新位于内存中的out_var。关于常用的约束规则,本文后面会给出说明。
若输出有多个,则典型格式示例如下:
asm ( "cpuid"
: "=a" (out_var1), "=b" (out_var2), "=c" (out_var3)
: "a" (op)
);

可见,我们可以为每个output operand指定其约束。


4)input operands
该字段为可选项,用以指明输入操作数,其典型格式为:
: "constraints" (in_var)
其中,constraints可以是gcc支持的各种约束方式,in_var通常为C语言提供的输入变量。
与output operands类似,当有多个input时,典型格式为:
: "constraints1" (in_var1), "constraints2" (in_var2), "constraints3" (in_var3), ...
当然,input operands + output operands的总数通常是有限制的,考虑到每种指令集体系结构对其涉及到的指令支持的最多操作数通常也有限制,此处的操作数限制也不难理解。此处具体的上限为max(10, max_in_instruction),其中max_in_instruction为ISA中拥有最多操作数的那条指令包含的操作数数目。需要明确的是,在指明input operands的情况下,即使指令不会产生output operands,其:也需要给出。例如asm ("sidt %0\n" : :"m"(loc)); 该指令即使没有具体的output operands也要将:写全,因为有后面跟着: input operands字段。


5)list of clobbered registers
该字段为可选项,用于列出指令中涉及到的且没出现在output operands字段及input
operands字段的那些寄存器。若寄存器被列入clobber-list,则等于是告诉gcc,这些寄
存器可能会被内联汇编命令改写。因此,执行内联汇编的过程中,这些寄存器就不会被gcc
分配给其它进程或命令使用。

linux内嵌汇编语言 虽然Linux的核心代码大部分是用C语言编写的,但是不可避免的其中还是有一部分是用汇编语言写成的。有些汇编语言代码是直接写在汇编源程序中的,特别是Linux的启动代码部分;还有一些则是利用gcc的内嵌汇编语言嵌在C语言程序中的。这篇文章简单介绍了gcc中的内嵌式汇编语言,主要想帮助那些才开始阅读Linux核心代码的朋友们能够更快的入手。 写这篇文章的主要信息来源是GNU的两个info文件:as.info和gcc.info,如果你觉得这篇文章中的介绍还不够详细的话,你可以查阅这两个文件。当然,直接查阅这两个文件可以获得更加权威的信息。如果你不想被这两篇文档中的一大堆信息搞迷糊的话,我建议你先阅读一下这篇文章,然后在必要时再去查阅更权威的信息。 立即下载

相关推荐

别再让地图加载慢吞吞!GeoServer + GeoWebCache 缓存配置实战(附性能对比)

本文详细介绍了如何通过GeoServer和GeoWebCache优化地图服务性能,实现地图加载速度的显著提升。从缓存机制解析到实战配置流程,再到高级性能调优技巧,帮助开发者构建高效地图缓存系统,解决地图加载慢的问题。

weixin_42525369的博客 407

Linux内联汇编

指定编译器将函数的代码插入到调用者的代码中,直到实际调用的位置,这些函数是内联函数。与宏有一些相似之处,它的好处是可以减少函数调用的开销,如果任何实际参数是常量,则他们的已知值可能允许在编译时进行简化,因此不需要包含所有内联函数的代码内联汇编其实就是编写为内联函数的汇编程序,为什么使用它呢,因为它能够操作并使其输出在C变量的上可见,调用asm关键字,声明其为内联函数。

2301_76226118的博客 1720

蓝牙抓包实战:用nrf52840和Wireshark解析广播包与SCAN_RSP的完整流程

本文提供了一份完整的蓝牙抓包实战指南,详细介绍了如何使用nRF52840 Dongle和Wireshark捕获并解析蓝牙广播包与SCAN_RSP。内容涵盖环境搭建、广播事件分析、数据包结构拆解以及常见连接问题的调试技巧,旨在帮助开发者和物联网工程师深入理解BLE底层通信,提升硬件调试能力。

weixin_29279153的博客 495

linux内核中断、异常、系统调用的分析以及实践

 中断、异常、系统调用的分析  报告内容中断是由间隔定时器和和I/O设备产生的。异常则是由程序的错误产生,或者由内核必须处理的异常条件产生。第一种情况下,内核通过发送一个信号来处理异常;第二种情况下,内核执行恢复异常需要的所有步骤,或对内核服务的一个请求。中断和异常改变处理器执行的指令顺序,通常与CPU芯片内部或外部硬件电路产生的电信号相对应。它们提供了一种特殊的方式,使处

Icyfire Talks 4921

保姆级教程:用ROS2 Humble和激光雷达,5分钟搞定机器人避障(附Python代码)

本文提供了一份详细的ROS2 Humble激光雷达避障实战指南,帮助开发者快速实现机器人避障功能。通过环境配置、硬件连接和Python代码实现,5分钟内即可让机器人自主避开障碍物。文章还涵盖了参数调优、常见问题排查及进阶优化技巧,适合机器人开发初学者和进阶用户。

weixin_42528902的博客 342

Android 14.0 开机广播接收慢广播延迟问题分析

在14.0的系统rom定制化开发中,在某些时候在接收开机广播的时候发现,过了一分钟才收到开机广播,接下来就需要分析下 开机广播的相关分发机制,来处理下相关问题

安卓兼职framework和app工程师的博客 631

Linux Kernel 源码学习必备知识之:GCC 内联汇编(AT&T格式)

原因是即使寄存器只变动一部分,它的整体也会全跟着受影响,所以在 clobber/modiy 句中声明寄存器时,可以用低 8 位名称、低 16 位名称或低 32 位或全 64 位名称,如"al"、"ax"、"eax"、"rax" 都是指 rax 寄存器,其他通用寄存器也是一样的。单独强调一下,以上的 output() 和 intput() 括号中的是 C 代码中的变量,output(C变量)和input(C变量) 就像 C 语言中的函数,将 C 变量(值或变量地址)转换成汇编代码的操作数。

嵌入式Linux内核的博客 3334

Java Swing教程-16. Swing中的图形绘制

这篇教程介绍了Java Swing中的图形绘制功能,主要内容包括: Graphics类的基本使用 - 介绍了如何重写paintComponent方法实现自定义绘制,以及基本图形绘制方法(线条、矩形、椭圆、多边形等) 文本与图片绘制 - 讲解了文本绘制方法、字体设置和图片加载绘制技术 颜色与字体设置 - 包括预定义颜色、RGB自定义颜色、透明色设置以及字体样式控制 案例实现 - 提供了一个简单绘图程序的框架,支持鼠标绘制不同图形、选择工具和自定义颜色等功能 教程通过代码示例详细演示了各种绘图操作,适合Java

无 233

Linux内核中的内联汇编

内联汇编是一种在高级编程语言(如C或C++)中直接嵌入汇编代码的技术。这种方法允许程序员在源代码中直接插入汇编指令,从而实现对底层硬件的更直接控制和优化。内联汇编通常使用asm关键字将汇编代码嵌入到C/C++源代码中。

qq_45652092的博客 1302

基于 ESP32+IMU+BLE HID 的低延迟无线体感游戏控制器设计与实现

本文设计的基于 ESP32 的低延迟无线体感游戏控制器,通过合理的硬件选型与软件优化,实现了体感姿态感知与无线低延迟传输的核心功能。硬件上采用 ESP32+MPU6050+TP4056 的低成本方案,接线简单、便携性强;软件上通过轻量化库、互补滤波算法与非阻塞 BLE 传输,有效降低了系统延迟,满足体感游戏的使用需求。

weixin_42300449的博客 401

ComfyUI 本地部署指南:概念、部署过程、生成图片、共享 WebUI 模型

ComfyUI 是一个基于节点的 Stable Diffusion 图形化用户界面。您可以通过将不同的节点连接在一起来构建生成图像的工作流程。一些常用的节点包括加载检查点模型(Load Checkpoint)、输入提示词(CLIP Text Encode)、指定采样器(KSampler)等。ComfyUI 将工作流程分解为可重新排列的元素,以便您可以轻松创建自己的元素。

水滴的博客 5032

【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly。本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^)。        注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,二者的区

slvher的专栏 2万+

Node-RED教程(二):Node-RED的面板的操作

Node-RED系列(二):Node-RED的面板的操作 要使用Node-RED去搭建一个物联网平台,链接设备,设备通信,就必须要先熟悉Node-RED的这种面板,对于一个新的项目,在动手做之前一点想对这个的技术的文档有足够的了解做起来才能游刃有余。本期我给大家介绍一下Node-RED的各种面板,熟悉这些面板后,在后续的搭建Iot服务中,会举重若轻,同时该系列的文档,难度会逐步加深,知道了本章解释的名称后对后续文章的理解有很大帮助。 面板1:默认节点选项列表 安装Node-RED后默认的节点分为这5大类

知无涯 1万+

Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)【转】

转自:http://www.linuxidc.com/Linux/2013-06/85221p3.htm 阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly。本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^)。 ...

weixin_33782386的博客 163

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Linux汇编out语法,Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)...

3. 实例剖析前面介绍了很多理论性的规则,这里通过分析一个实例来加深对inline assembly的理解。下面的代码是Linux内核i386版本中的syscall0定义:#define _syscall0(type, name) \type name(void) \{ ...

weixin_29208077的博客 198

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)---- asm [volatile](**)

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly。本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^)。 注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,二者的区别参见这里),

zyllong的专栏 4241

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

[转载]【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)...

在阅读Linux内核源码或对代码做性能优化时,经常会有在C语言中嵌入一段汇编代码的需求,这种嵌入汇编在CS术语上叫做inline assembly。本文的笔记试图说明Inline Assembly的基本语法规则和用法(建议英文阅读能力较强的同学直接阅读本文参考资料中推荐的技术文章 ^_^)。 注意:由于gcc采用AT&T风格的汇编语法(与Intel Syntax相对应,...

weixin_30641465的博客 107

【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)...

http://blog.youkuaiyun.com/slvher/article/details/8864996 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html 转载于:https://www.cnblogs.com/woshare/p/5825830.html

weixin_34304013的博客 122

Linux ARM平台上的内联汇编学习(asm ,inline assembly)

在Linux+ARM平台上使用内联汇编(inline assembly),可以通过GCC(GNU Compiler Collection)提供的内联汇编语法来实现。内联汇编允许开发者在C/C++代码中直接嵌入汇编指令,对于编写性能敏感的代码、访问特定硬件特性或者实现某些底层功能非常有用。下面就结合内联汇编的优缺点为出发点,明白为什么要学习和掌握它,以及以一个内联汇编代码为例,熟悉一下内联汇编相关语法规则。内联汇编作为一种在高级语言代码中直接嵌入低级机器指令的技术,具有其独特的优势和潜在的局限性。

1551
上一篇: C语言函数之可变参数原理:va_start、va_arg及va_end
下一篇: C程序的BSS段 代码段 数据段
LinuxWorking
博客等级 码龄10年 24粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值