gcc 内嵌汇编的学习笔记 I

gcc内嵌汇编介绍 阅读Android或Linux的源码时,有时会遇到使用内嵌汇编的代码。阅读内嵌汇编代码不是一件特别容易的事,如果只了解普通汇编语言,没学习过内嵌汇编,从语言上大概能明白内嵌汇编代码的作用,但是要精确的了解每行代码,每个寄存器的含义就不太可能了。内嵌汇编其实并不复杂,只不过gcc的内嵌汇编必须是AT&T格式,而且有自己一套独特的标记,加上资料很少,有限的资料写的又很晦涩,所以学习起来比较困难。本文争 阅读详情

gcc 内嵌汇编的学习笔记 I
                           --第一个混合编码的加法计算器
  作者:ShellEx. 
  ShellEx.cn && blog.youkuaiyun.com/shellex 版权所有
  
写了一段简单的代码:

#include <stdio.h>
int main() {
 int in1 = 0, in2 = 0, out = 0;
 printf("PLZ input 2 Number like this: (x1 + x2) /n");
 scanf("%d + %d", &in1, &in2);
 asm volatile(
  "add %1, %0/n/t"
  "add %2, %0/n/t"
  "nop/n/t"
  :"=r"(out)
  :"r"(in1),"r"(in2)
  :
 );
 printf("%d + %d = %d./n", in1, in2, out);
 return 0;
}
///////////////////////////////////////////////////////////////
输入两数,求他们的和。心想估计没有问题,就编译运行。
运行结果:
PLZ input 2 Number like this: (x1 + x2)
2+3
2 + 3 = 10.
晕一个,和我想的不一样啊。去看看汇编代码吧(gcc加上-S参数可以生
成汇编源文件):

...
 movl $0, -4(%ebp)
 movl $0, -8(%ebp)
 movl $0, -12(%ebp)
...
 movl -4(%ebp), %edx
 movl -8(%ebp), %eax
/APP
 add %edx, %eax
 add %eax, %eax
 nop
 
/NO_APP
 movl %eax, -12(%ebp)
 movl -12(%ebp), %eax
...
///////////////////////////////////////////////////////////////
以上代码仅仅关键部分,前后有省略。在/APP和/NO_APP之间的是内嵌汇
编部分。可以看到,gcc先把-4(%ebp)和-8(%ebp)(分别是in1和in2)
放入%edx和%eax寄存器,然后执行第一个add使得eax保存有两个数的和,
第二个add又把eax加在自己身上,最后把eax的值赋给-12(%ebp)也就是
out.功能大约相当于下面的C++代码:
tmp1 = in1;
tmp2 = in2;
tmp1 += tmp2;
tmp1 += tmp1;
out = tmp1;
结果当然不对啦。这是由于gcc不知道错误地使用eax寄存器造成的。他并
不知道%2和%0用了同一个寄存器呢。所以我在输出部分加入"&"限制符。

 asm volatile(
  "add %1, %0/n/t"
  "add %2, %0/n/t"
  "nop/n/t"
  :"=&r"(out)
  :"r"(in1),"r"(in2)
  :
 );
 
///////////////////////////////////////////////////////////////
编译执行:
PLZ input 2 Number like this: (x1 + x2)
2+3
2 + 3 = 2009143897.
又出现了奇怪的问题。再看看汇编代码:

 movl -4(%ebp), %edx
 movl -8(%ebp), %eax
/APP
 add %edx, %ecx
 add %eax, %ecx
 nop
 
/NO_APP
 movl %ecx, %eax
 movl %eax, -12(%ebp)
///////////////////////////////////////////////////////////////
貌似没问题,其实不然。存放结果的ecx寄存器并没有一开始就把out
的值读入(不像in1 和 in2,被读入edx和eax)。说明gcc对于使用"r"
限制符的输出变量,并没有像对待输入变量那样分配完寄存器后就读入
值。资料表明,这个行为可能是由于AT&T汇编源于CISC架构处理器的汇
编语言,在CISC架构处理器中大部分指令输入输出明显分开,而不像
RISC架构处理器那样一个操作数可以输出也可以输入。
所以我应该让gcc知道,我的out也应该享受同等待遇。

#include <stdio.h>
int main() {
 int in1 = 0, in2 = 0, out = 0;
 printf("PLZ input 2 Number like this: (x1 + x2) /n");
 scanf("%d + %d", &in1, &in2);
 asm volatile(
  "add %1, %0/n/t"
  "add %2, %0/n/t"
  "nop/n/t"
  :"=&r"(out)
  :"r"(in1),"r"(in2),"0"(out)
  :
 );
 printf("%d + %d = %d./n", in1, in2, out);
 return 0;
}
///////////////////////////////////////////////////////////////
在输入部分添加对out的描述,并且用限定符"0"指定out就是输入部分的
那个%0.因为gcc是不会去判断%1和%3是否关联自同一个变量的。所以需要
显性指定。
汇编代码如下。

 movl -4(%ebp), %ecx
 movl -8(%ebp), %edx
 movl -12(%ebp), %eax
/APP
 add %ecx, %eax
 add %edx, %eax
 nop
 
/NO_APP
 movl %eax, -12(%ebp)
///////////////////////////////////////////////////////////////
编译运行的输出也是正确的了:
PLZ input 2 Number like this: (x1 + x2)
2+3
2 + 3 = 5. 
但是这么写真是麻烦。其实有个更简单的方法,就是使用"+"限定符。表
示操作数可以读和写。
 
 asm volatile(
  "add %1, %0/n/t"
  "add %2, %0/n/t"
  "nop/n/t"
  :"+r"(out)
  :"r"(in1),"r"(in2)
  :
 );
/////////////////////////////////////////////////////////////// 
汇编代码如下:


 movl -12(%ebp), %edx
 movl -4(%ebp), %ecx
 movl -8(%ebp), %eax
/APP
 add %ecx, %edx
 add %eax, %edx
 nop
 
/NO_APP
 movl %edx, -12(%ebp)
 
/////////////////////////////////////////////////////////////// 
没想到才刚刚开始就遇到这么多问题,记录下来,就算是学习笔记。既然
是笔记,如果看官们发现错误,请一定不吝赐教。谢谢观赏。

shellex.cn && blog.youkuaiyun.com/shellex 版权所有 

gnu嵌入汇编,内嵌汇编详细的介绍 GCC 提供了内嵌汇编的功能,可以在 C 代码中直接内嵌汇编语言语句,大大方便了程序设计。简单的内嵌汇编很容易理解,例: __asm__ __volatile__("hlt"); "__asm__" 表示后面的代码为内嵌汇编,“asm”是“__asm__”的别名。 “__volatile__” 表示编译器不要优化代码,后面的指令保留原样,“volatile”是它的别名。 括号里面是汇编指令。 ... 阅读详情

相关推荐

内嵌汇编

内嵌汇编 操作系统高级教程上面需要阅读Linux内核0.11的源码,其中在书《Linux内核设计的一书》第2.5节异常处理类中段服务程序挂接的部分,遇到了嵌入在C语言中的汇编代码,之前从来没有学习过汇编,因此记录下。 AT&T基础知识 内嵌汇编使用的是AT&T汇编,所以首先稍微讲解下AT&T的汇编指令的基础知识。 操作数前缀 movl $8,%eax movl ...

qq_33620071的博客 2534

GCC内嵌汇编之语法详解

开发Arm程序的时候,大多数时候使用C/C++语言就可以了,但汇编语言在某些情况下能够实现一些C语言无法实现的功能,这时候就要调用一些汇编语言的程序.我们需要大概了解一下在C语言中如何嵌入汇编语言.内嵌汇编语法如下:        __asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分) 共四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:”格开,汇编语句模板必...

开挂的熊猫 1万+

GCC 内嵌汇编语法详解+visual studio code实操

开发Arm程序的时候,大多数时候使用C/C++语言就可以了,但汇编语言在某些情况下能够实现一些C语言无法实现的功能,这时候就要调用一些汇编语言的程序.我们需要大概了解一下在C语言中如何嵌入汇编语言。 《1》内嵌汇编语法如下: __asm__(汇编语句模板: 输出部分: 输入部分: 破坏描述部分) 共四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:”格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开...

qfturauyls的博客 3463

AT&T汇编语言与GCC内嵌汇编简介

   1 AT&T 与INTEL的汇编语言语法的区别1.1大小写1.2操作数赋值方向1.3前缀1.4间接寻址语法1.5后缀1.6指令 2 GCC内嵌汇编2.1简介2.2内嵌汇编举例2.3语法2.3.1汇编语句模板2.3.2输出部分2.3.3输入部分2.3.4限制字符2.3.5破坏描述部分2.4GCC如何编译内嵌汇编代码 

界外 3161

GCC嵌入式汇编(内嵌汇编)入门

GCC嵌入式汇编(内嵌汇编)入门 1、 入门 在C中嵌入汇编的最大问题是如何将C语言变量与指令操作数相关联。当然,gcc都帮我们想好了。下面是是一个简单例子。 asm(“fsinx %1, %0”:”=f”(result):”f”(angle)); 这里我们不需要关注fsinx指令是干啥的;只需要知道这条指令需要两个浮点寄存器作为操作数。作为专职处理C语言的gcc编

成长Bar的博客专栏 4788

关于GCC内联汇编(也可以叫内嵌汇编)的简单学习

asm("汇编语句": 输出部分: 输入部分: 会被修改的部分);共四个部分,其中汇编语句必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。

zhanghui962623727的博客 1301

gcc内嵌汇编语法分析

简单来讲是gcc优化的需要,gcc只要保证一个符号在他使用前将其准备好就可以了,如果使用**“=”**修饰一个符号则是告诉编译器,内嵌汇编中不会用到这个值,所以gcc也不用在这段内嵌汇编前把这个值准备好,又因为gcc在编译阶段并不会分析内嵌汇编程序,所以即使在内嵌汇编中使用了这个值,编译器也不会报错,但这个值可能不是预期的。编译阶段仅仅会解析“输出部”,“输入部”,“破坏部”, “GotoLabels”,程序员也是同步这四个部分告诉编译器执行这段内嵌汇编可能发生的情况,如可能破坏寄存器,或者修改内存。

dmf_fff的博客 2023

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

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

yolo模型训练找我,AI游戏合作找我 7万+

gcc 内嵌汇编的学习笔记 IV

             gcc 内嵌汇编的学习笔记 IV                             --函数调用  作者:ShellEx.   ShellEx.cn && blog.youkuaiyun.com/shellex 版权所有 没有经验,还是通过反汇编出来的代码来学习。先写一个简单的函数调用的C++ code Sample:#include int Add(int a, int

钢窟. 3877

ESP8266 进行HDLC解码,AX.25,APRS

/************************************************************** 函数名:aprs_wait_begin() 参 数:无 返回值:bool true=得到合法脉冲,false=未得到 说 明:等待第1个833us高脉冲,判断范围 730-930,其他忽略 ***************************************************************/ bool aprs_wait_begin(){ stati

蓝蓝的博客 1625

嵌入式学习(29)-ASM330LHH驱动程序

ASM330LHH是一种系统级封装器件,具有3D数字加速度计和3D数字陀螺仪,扩展温度范围上限为+105 °C,适用于汽车非安全领域的应用。ASM330LHH 的满量程加速范围为±2 g、±4 g、±8 g 和 ±16 g,角速度范围扩展至 ±125 dps、±250 dps、±500 dps、±1000 dps、± 2000 dps 和 ±4000 dps,适合各种汽车应用。

剑藏锋的博客 1175

gcc中的内嵌汇编语言

 gcc中的内嵌汇编语言(Intel i386平台) 一.声明 虽然Linux的核心代码大部分是用C语言编写的,但是不可避免的其中 还是有一部分是用汇编语言写成的。有些汇编语言代码是直接写在汇 编源程序中的,特别是Linux的启动代码部分;还有一些则是利用gcc 的内嵌汇编语言嵌在C语言程序中的。这篇文章简单介绍了gcc中的内 嵌式汇编语言,主要想帮助那些才开始阅读Linux核心代码的朋友

小春的药匣子 3171

3D Slicer肺部CT病灶体积测量:阈值法实操全流程

在医学影像分析中,病灶体积的精准测量是肿瘤评估、疗效随访和科研统计的重要基础。传统逐层手动勾画不仅耗时,且主观差异大,而基于CT值的阈值分割技术,通过设定灰度区间自动提取目标体素,能够快速生成三维分割结果,具有高效、可重复、边界标准统一的优势,尤其适用于肺部实性结节这类与周围肺实质对比度高的病灶。理解体素与CT值的关系,掌握阈值范围的设定逻辑,并配合连通域分析、边缘修正等工程化操作,即可在3D Slicer中稳定获得可靠的体积数据。本文从技术原理出发,系统梳理了DICOM导入、窗宽窗位调节、阈值选择、三维重

weixin_29050271的博客 251

GCC内嵌汇编(一)

由于工作的需要,所以花了几天时间从网上找了不少资料学习了一下GCC内嵌汇编,在此把我所认为比较重要的部分跟大家分享下,同时也在此感谢那些发表GCC内嵌汇编相关文章的作者!在此也希望我整理的资料对需要学习GCC内嵌汇编的朋友有所帮助。因为内容比较多,所以我特地把

bigloomy的专栏 5404

分布式爬虫架构实战:Scrapy+RabbitMQ+浏览器池,百万级数据抓取成本直降60%(附架构图+源码)

任务调度瓶颈:Redis 作为消息队列,不支持复杂任务优先级,高并发下容易消息堆积,且单点故障会导致全量任务丢失;资源浪费严重:每个爬虫节点每次爬取动态页面都启动新浏览器,启动耗时3-5秒,CPU 占用率高达80%+,单机最多同时跑3个浏览器;扩展性差:新增节点需要手动同步任务队列,节点忙闲不均,无法根据任务量动态分配资源。# 从settings读取RabbitMQ配置# 注册信号:爬虫关闭时关闭RabbitMQ连接"""启动时建立RabbitMQ连接"""

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1617

MIKE水动力笔记7_实测数据与模型输出结果的拟合对比

上一博文【MIKE水动力笔记6】主要讲解如何自己制作实测数据的时间序列文件dfs0,而本博文讲解如何进行实测数据与模型输出结果的拟合对比。

晏长街的博客 1万+

GCC内嵌汇编(三)

接下来是GCC内嵌汇编最后一部分了,  可能看起来讲的先后顺序有些乱,但是个人习惯吧,前面如果有些地方不明白的,看了后面的应该就清楚了。如果还是有疑惑的话,自己组织下内容效果更佳。匹配限制符 I386 指令集中许多指令的操作数是读写型的(读写型操作数指先读取原

bigloomy的专栏 4757

从 Open SQL JOIN 走向 ABAP CDS Association:把查询写成可复用的数据模型

摘要: 本文通过飞行模型示例,对比了ABAP中三种表关联实现方式:Open SQL JOIN、CDS显式JOIN和CDS Association。重点解析了Association的本质是将表关系声明为数据模型语言,使用时通过路径表达式按需展开为JOIN。文章指出路径表达式在不同位置会默认展开为不同JOIN类型(如SELECT列表默认为LEFT OUTER),并演示了如何用[inner]强制指定INNER JOIN。最后结合S/4HANA实际案例,说明Association通过中心化关系定义和路径复用,能有效

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 377

gcc内嵌汇编简介

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

小白笔记本 563

从通用到定制:营销Agent如何跨越数据鸿沟,实现对话SOP的个性化飞跃

从通用到定制:营销Agent如何跨越数据鸿沟,实现对话SOP的个性化飞跃

丨汀、的博客 656

基于STM32的智能手环心率血氧体温监测系统(完整设计)

本文设计了一款基于STM32单片机的多功能智能手环系统,集成心率、血氧、体温实时监测功能,并支持运动数据管理与健康预警。系统采用MAX30102传感器实现心率血氧监测,DS18B20检测体温,ADXL345进行步数统计,通过OLED屏幕显示数据。研究通过低功耗硬件选型与模块化软件架构设计,实现了多参数同步采集、阈值预警及蓝牙数据传输功能。测试结果表明,系统在健康监测精度、续航能力及用户交互体验上均达到预期目标,为个人健康管理提供了实用解决方案。

3254968421的博客 701

gcc内嵌汇编简单介绍,以及 __asm__ volatile ("": : :"memory")中memory解释

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

szhlcy的博客 5163

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

gcc 内嵌汇编用法

内核代码绝大部分使用C语言编写,只有一小部分使用汇编语言编写,例如与特定体系结构相关的代码和对性能影响很大的代码。GCC提供了内嵌汇编的功能,可以在C代码中直接内嵌汇编语言语句,大大方便了程序设计。 简单的内嵌汇编很容易理解 例: __asm__ __volatile__("hlt"); “__asm__”表示后面的代码为内嵌汇编,“asm”是“__asm__”的别名。

如丧 486

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

GCC 内嵌汇编之扩展的行内汇编

扩展的行内汇编 在扩展的行内汇编中,可以将 C 语言表达式指定为汇编指令的操作数,而且不用去管如何将 C 语言表达式的值读入寄存器,以及如何将计算结果写回 C 变量,你只要告诉程序中 C 语言表达式与汇编指令操作数之间的对应关系即可,GCC 会自动插入代码完成必要的操作。 使用内嵌汇编,要先编写汇编指令模板,然后将 C 语言表达式与指令的操作数相关联,并告诉 GCC 对这些操作有哪些...

diyudong4681的博客 275

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

GCC内嵌汇编简介- - zz

                                        在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作。 1、简单的内嵌汇编 例:       __asm__ _

小春的药匣子 1435

zz:gcc内嵌汇编

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

761
上一篇: U盘文件丢失了!哭吧~ShellEx
下一篇: gcc 内嵌汇编的学习笔记 II
ShellEx
博客等级 码龄21年 4粉丝 43原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值