GCC 内联汇编
LINUX下的汇编入门
AT&T风格 汇编 和GCC风格汇编
汇编代码的调试
前面写了三篇,是自我摸索三篇,摸着石头过河,有些或许是错误的细节,不必在意! 今天我们直接用GCC编译C语言代码,且在C语言里面内嵌AT&T风格的汇编! 前三篇大家了解即可,我们重点放在内嵌汇编里,简单快捷舒服!
GCC支持在C/C++代码中嵌入汇编代码,这些汇编代码被称作GCC Inline ASM——GCC内联汇编。
这是一个非常有用的功能,有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中,另外也允许我们直接写C/C++代码中使用汇编编写简洁高效的代码。其实为了装逼和护城河!
gcc 编译器支持 2 种形式的内联 asm 代码:
基本 asm 格式:不支持操作数;
扩展 asm 格式:支持操作数;
1. 语法规则
asm [volatile] ("汇编指令")
所有指令,必须用双引号包裹起来;
超过一条指令,必须用\n分隔符进行分割,为了排版,一般会加上\t;
多条汇编指令,可以写在一行,也可以写在多行;
关键字 asm 可以使用 asm 来替换;
volatile 是可选的,编译器有可能对汇编代码进行优化,使用 volatile 关键字之后,告诉编译器不要优化手写的内联汇编代码。
基本内联汇编的格式是
__asm__ __volatile__("Instruction List");
可选风格 有比较多种,不过测试了下 就下面代码的风格支持得好,
每行汇编命令 要加冒号和\N\T 确实麻烦. 不过可以使用软件前后追加特定符号就行了.
下面是基本格式 不支持操作数,它必须使用全局变量,这限制太麻烦了
#include <stdio.h>int a = 1;
int b = 2;
int c;int main()
{asm volatile ("movl a, %eax\n\t""addl b, %eax\n\t""movl %eax, c");printf("c = %d \n", c);return 0;
}
其实汇编内嵌 相当于调用个C函数而已,不过这C函数是汇编函数而已
#include <stdio.h>int main()
{int data1 = 1;int data2 = 2;int data3;asm volatile("movl %%ebx, %%eax\n\t""addl %%ecx, %%eax": "=a"(data3) : "b"(data1),"c"(data2)
);/*asm [volatile] ("汇编指令\n\t" : "输出操作数列表" : "输入操作数列表" : "改动的寄存器")*/printf("data3 = %d \n", data3);return 0;
}
这里必须使用扩展ASM格式,才能不使用全局变量当作参数传入汇编函数里
所以汇编命令 寄存器要多个%号 "movl %%ebx,%%eax" 把EBX的值覆盖进EAX里.
所有汇编命令结束后 最后个小挂号前 开始定义我们的函数参数
第一个冒开始是 输出参数 :"=a"(data3)
第二个冒号开始是 输入参数 有多个参数用逗号分隔
第三个冒号是不要优化寄存器列表
其中 :"=a"(data3) 的 data3 是C的变量 用小挂号保护起来, 前面的=A
叫做"修饰符"
对输出寄存器或内存地址提供额外的说明,包括下面4个修饰符:
+:被修饰的操作数可以读取,可以写入;
=:被修饰的操作数只能写入;
%:被修饰的操作数可以和下一个操作数互换;
&:在内联函数完成之前,可以删除或者重新使用被修饰的操作数;
其中A 使用寄存器的别名 "=a" 表示只能写A的寄出器(EAX)
通俗讲下面的叫约束
a: 使用 eax/ax/al 寄存器;
b: 使用 ebx/bx/bl 寄存器;
c: 使用 ecx/cx/cl 寄存器;
d: 使用 edx/dx/dl 寄存器;
r: 使用任何可用的通用寄存器;
m: 使用变量的内存位置;
b(data1)表示 data1变量的值复制到B寄出器里
在内联汇编代码中,没有声明“改动的寄存器”列表,也就是说可以省略掉(前面的冒号也不需要);
使用占位符来代替寄存器名称
如果操作数有很多,那么在内联汇编代码中去写每个寄存器的名称,就显得很不方便。占位符有点类似于批处理脚本中,利用 2...来引用输入参数一样,内联汇编代码中的占位符,从输出操作数列表中的寄存器开始从 0 编号,一直编号到输入操作数列表中的所有寄存器。
#include <stdio.h>
int main()
{int data1 = 1;int data2 = 2;int data3;asm( "movl %1, %%eax\n\t""addl %2, %0": "=r"(data3) : "r"(data1),"r"(data2) );printf("data3 = %d \n", data3);return 0;
}
%0 是输入参数 依次是 两个输入参数 %1 %2
内联汇编的C语言 正常编译就好了
[root@dsmart=>LINUX_ASM]$gcc main_add.c -o main.add.exe
[root@dsmart=>LINUX_ASM]$./main.add.exe
data3 = 3
我们可以查看下GCC 汇编的代码
[root@dsmart=>LINUX_ASM]$gcc -S main_add.c -o main_add.asm
[root@dsmart=>LINUX_ASM]$vim main_add.asm
下面是我们GCC把MAIN_ADD.C全部翻译成了汇编代码,而我们重点的内嵌汇编用蓝色注解#APP----#NOAPP 范围内
.file "main_add.c".section .rodata
.LC0:.string "data3 = %d \n".text.globl main.type main, @function
main:
.LFB0:.cfi_startprocpushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6subq $16, %rspmovl $1, -4(%rbp)movl $2, -8(%rbp)movl -4(%rbp), %eaxmovl -8(%rbp), %edx
#APP
# 9 "main_add.c" 1movl %eax, %eaxaddl %edx, %eax# 0 "" 2
#NO_APPmovl %eax, -12(%rbp)movl -12(%rbp), %eaxmovl %eax, %esimovl $.LC0, %edimovl $0, %eaxcall printfmovl $0, %eaxleave.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size main, .-main.ident "GCC: (GNU) 5.5.0" .section .note.GNU-stack,"",@progbits
里面这段代码不是%1了,被具体替换成了寄出器名.
这段是C语言调用汇编函数进行参数压栈操作,分别把参数1,2压入栈底
movl $1, -4(%rbp)
movl $2, -8(%rbp)
movl -4(%rbp), %eax
movl -8(%rbp), %edx
rsp : 栈指针寄存器,指向栈顶
rbp : 栈基址寄存器,指向栈底
返回参数:
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
把结果 压入栈底 -12位置,然后出栈 把RBP栈的值 返回给EAX
好像这有点多余
下面准备调用PRINTF函数edi : 函数参数
rsi/esi : 函数参数
下面我们进行O3优化下看
[root@dsmart=>LINUX_ASM]$gcc main_add.c -S -O3 -o main_add.asm
代码确实少了些
.file "main_add.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "data3 = %d \n"
.section .text.unlikely,"ax",@progbits
.LCOLDB1:
.section .text.startup,"ax",@progbits
.LHOTB1:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB11:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $2, %esi
movl $1, %eax
#APP
# 9 "main_add.c" 1
movl %eax, %eax
addl %esi, %esi
# 0 "" 2
#NO_APP
movl $.LC0, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE11:
.size main, .-main
.section .text.unlikely
.LCOLDE1:
.section .text.startup
.LHOTE1:
.ident "GCC: (GNU) 5.5.0"
.section .note.GNU-stack,"",@progbits
结果优化的不像人样了,volatile 也无法禁止优化内嵌汇编!
相关文章:

GCC 内联汇编
LINUX下的汇编入门 AT&T风格 汇编 和GCC风格汇编 汇编代码的调试 前面写了三篇,是自我摸索三篇,摸着石头过河,有些或许是错误的细节,不必在意! 今天我们直接用GCC编译C语言代码,且在C语言里面内嵌AT&T风格的汇编! 前三篇大家了解即可,我们重点放在内嵌汇编里,简单快…...

springboot整合websocket后启动报错:javax.websocket.server.ServerContainer not available
一、场景 Springboot使用ServerEndpoint来建立websocket链接。引入依赖。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>配置Websocket Confi…...
Vue面试之生命周期(上篇)
Vue面试之生命周期(上篇) 创建阶段beforeCreatecreated挂载阶段beforeMountmounted更新阶段beforeUpdateupdated销毁阶段beforeDestroydestroyed补充说明activated...

Gin 框架之用户密码加密
文章目录 一、引入二、密码加密位置三、如何加密四、bcrypt 库加密4.1 介绍4.2 优点:4.3 使用 五、小黄书密码加密实践 一、引入 Gin是一个用Go语言编写的Web框架,而用户密码的加密通常是在应用程序中处理用户身份验证时的一个重要问题。 通常敏感信息…...

【创作活动】ChatGPT 和文心一言哪个更好用?
文章目录 文心一言优点缺点 ChatGPT优点缺点 Java编码能力比较对人工智能的看法 ChatGPT是由OpenAI开发的交互式AI大模型, 文心一言是由百度研发的知识增强大语言模型,本文从Java开发的角度对比一下哪个更好用(本文仅用于投稿CSDN创造活动&am…...

【linux】查看Debian应用程序图标对应的可执行命令
在Debian系统中,应用程序图标通常与.desktop文件关联。您可以通过查看.desktop文件来找到对应的可执行命令。这些文件通常位于/usr/share/applications/或~/.local/share/applications/目录下。这里是如何查找的步骤: 1. 打开文件管理器或终端。 2. 导…...

TortoiseSVN客户端如何安装配置并实现公网访问服务端提交文件到本地服务器
文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统,它与Apache Subversion(SVN)集成在一起,提供了一个用户友好的界面,方便用…...
【AUTOSAR】RTE 接口类型、应用场景差别及实例讲解
目录 摘要 概念 CS接口 SR接口 接口选择 对于CPU负载率的影响...

Qt应用开发(安卓篇)——Hello Qt On Android
一、前言 这一篇从实际出发,讲述如何创建、编译和部署Qt On Android项目。 二、ADB调试 ADB的全称为Android Debug Bridge,就是起到调试桥的作用,主要用于连接计算机与Android 设备,以便进行调试和数据传输。ADB 可以实现以下主要…...
第十三讲_css 伸缩盒模型flex
css 伸缩盒模型flex 1. 伸缩盒模型介绍2. 伸缩盒模型的主轴方向3. 伸缩盒模型的主轴换行4. 主轴上的对齐方式5. 侧轴上对齐方式5.1 一行的侧轴上对齐方式5.2 多行的侧轴上对齐方式 6. 伸缩项目的伸缩性6.1 伸缩项目在主轴上的基准长度6.2 伸缩项目的放大6.3 伸缩项目的缩小 7. …...

【C++干货铺】C++11常用新特性 | 列表初始化 | STL中的变化
个人主页点击直达:小白不是程序媛 C系列专栏:C干货铺 代码仓库:Gitee 目录 C11简介 列表初始化 std::initializer_list std::initializer_list使用场景 decltype关键字 STL中的一些变化 新容器 array forward_list 容器中的一些新…...

k8s的对外服务---ingress
service的作用体现在两个方面: 集群内部:不断追踪pod的变化。他会更新endpoint中的pod对象,基于pod的IP地址不断变化的一种服务发现机制。 集群外部:类似负载均衡器,把流量IP端口,不涉及转发url(http、htt…...

element-ui的el-upload组件实现上传拖拽排序图片顺序(sortablejs)
<template><!-- 省略其他配置 --><el-upload ref"upload" :file-list.sync"fileList"></el-upload></template><script>import Sortable from sortablejs;export default {data() {return {fileList: []};},mounted()…...

【PS】PS设计图欣赏、学习、借鉴
【PS】PS设计图欣赏、学习、借鉴 bilibili萌新PS学习计划:PS教程全套零基础教学视频(全套81节全新版本)...

游戏云化好吗?游戏云化会带来什么?
随着云计算技术的飞速发展,游戏云化成为游戏产业中备受关注的话题。这一新兴技术给玩家和游戏行业带来了全新的可能性。本文将深入探讨游戏云化的概念、优势以及可能带来的影响。 1、什么是游戏云化? 游戏云化是指将游戏的各个环节,包括游戏…...

制造业企业数字化转型难点剖析及解决之法
导语 全球正在由工业经济向数字经济转型过渡,制造业正在且并将长期处于数字化转型发展阶段,并沿着数字化、网络化、智能化阶段不断跃升。但如何找准数字化转型的切入点,以低耗能、低成本、高效率的方式加快制造业转型升级的步伐,仍…...
golang 服务端遇到strict-origin-when-cross-origin,解决跨域整理
golang 服务端遇到strict-origin-when-cross-origin,解决跨域整理 以下内容由chatgpt中文网 动态生成,助力开发找我 代码汇总: func Cors() gin.HandlerFunc {return func(c *gin.Context) {method : c.Request.Methodorigin : c.Request.Header.Get(…...

分布式事务Seata实战-AT模式(注册中心为Eureka)
大致记录Seata的AT模式下创建项目过程中需要注意的点和可能遇到的问题。 本项目是以官网的给的示例(即下图)进行创建的,以Eureka为注册中心。 官网:Seata AT 模式 | Apache Seata™ 官方代码示例: 快速启动 | Apac…...

windows vscode jsoncpp cmake c++ 构建项目
jsoncpp的编译和使用推荐文章:jsoncpp的编译和使用 | 爱编程的大丙 (subingwen.cn)https://www.subingwen.cn/cpp/jsoncpp/从这个链接下载jsoncpp-master:https://github.com/open-source-parsers/jsoncpp 可以把这个文件夹名字改成jsoncpp,…...
按照一定规则批量修改文件夹内文件的名称
#一个小朋友问我的问题,写好后,就想着分享出来# #目前只想到这一个普通的方法,应该还有更巧妙的方法,读者可以自己思考# 需求:给定文件夹40001,要求将该文件夹内的图片按照40001_00000001,40002_00000002…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...