当前位置: 首页 > news >正文

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 代码:

  1. 基本 asm 格式:不支持操作数;

  2. 扩展 asm 格式:支持操作数;

1. 语法规则

asm [volatile] ("汇编指令")

  1. 所有指令,必须用双引号包裹起来;

  2. 超过一条指令,必须用\n分隔符进行分割,为了排版,一般会加上\t;

  3. 多条汇编指令,可以写在一行,也可以写在多行;

  4. 关键字 asm 可以使用 asm 来替换;

  5. 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个修饰符:

  1. +:被修饰的操作数可以读取,可以写入;

  2. =:被修饰的操作数只能写入;

  3. %:被修饰的操作数可以和下一个操作数互换;

  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, @functionmain:.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 优点&#xff1a;4.3 使用 五、小黄书密码加密实践 一、引入 Gin是一个用Go语言编写的Web框架&#xff0c;而用户密码的加密通常是在应用程序中处理用户身份验证时的一个重要问题。 通常敏感信息…...

【创作活动】ChatGPT 和文心一言哪个更好用?

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

【linux】查看Debian应用程序图标对应的可执行命令

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

TortoiseSVN客户端如何安装配置并实现公网访问服务端提交文件到本地服务器

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…...

【AUTOSAR】RTE 接口类型、应用场景差别及实例讲解

目录 摘要 概念 CS接口 SR接口 接口选择 对于CPU负载率的影响...

Qt应用开发(安卓篇)——Hello Qt On Android

一、前言 这一篇从实际出发&#xff0c;讲述如何创建、编译和部署Qt On Android项目。 二、ADB调试 ADB的全称为Android Debug Bridge&#xff0c;就是起到调试桥的作用&#xff0c;主要用于连接计算机与Android 设备&#xff0c;以便进行调试和数据传输。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中的变化

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

k8s的对外服务---ingress

service的作用体现在两个方面&#xff1a; 集群内部&#xff1a;不断追踪pod的变化。他会更新endpoint中的pod对象&#xff0c;基于pod的IP地址不断变化的一种服务发现机制。 集群外部&#xff1a;类似负载均衡器&#xff0c;把流量IP端口&#xff0c;不涉及转发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学习计划&#xff1a;PS教程全套零基础教学视频&#xff08;全套81节全新版本&#xff09;...

游戏云化好吗?游戏云化会带来什么?

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

制造业企业数字化转型难点剖析及解决之法

导语 全球正在由工业经济向数字经济转型过渡&#xff0c;制造业正在且并将长期处于数字化转型发展阶段&#xff0c;并沿着数字化、网络化、智能化阶段不断跃升。但如何找准数字化转型的切入点&#xff0c;以低耗能、低成本、高效率的方式加快制造业转型升级的步伐&#xff0c;仍…...

golang 服务端遇到strict-origin-when-cross-origin,解决跨域整理

golang 服务端遇到strict-origin-when-cross-origin&#xff0c;解决跨域整理 以下内容由chatgpt中文网 动态生成,助力开发找我 代码汇总&#xff1a; func Cors() gin.HandlerFunc {return func(c *gin.Context) {method : c.Request.Methodorigin : c.Request.Header.Get(…...

分布式事务Seata实战-AT模式(注册中心为Eureka)

大致记录Seata的AT模式下创建项目过程中需要注意的点和可能遇到的问题。 本项目是以官网的给的示例&#xff08;即下图&#xff09;进行创建的&#xff0c;以Eureka为注册中心。 官网&#xff1a;Seata AT 模式 | Apache Seata™ 官方代码示例&#xff1a; 快速启动 | Apac…...

windows vscode jsoncpp cmake c++ 构建项目

jsoncpp的编译和使用推荐文章&#xff1a;jsoncpp的编译和使用 | 爱编程的大丙 (subingwen.cn)https://www.subingwen.cn/cpp/jsoncpp/从这个链接下载jsoncpp-master&#xff1a;https://github.com/open-source-parsers/jsoncpp 可以把这个文件夹名字改成jsoncpp&#xff0c;…...

按照一定规则批量修改文件夹内文件的名称

#一个小朋友问我的问题&#xff0c;写好后&#xff0c;就想着分享出来# #目前只想到这一个普通的方法&#xff0c;应该还有更巧妙的方法&#xff0c;读者可以自己思考# 需求&#xff1a;给定文件夹40001&#xff0c;要求将该文件夹内的图片按照40001_00000001,40002_00000002…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...