GCC&&G++ C && C++ 内嵌汇编和调用汇编函数的方法(x86,ARM自己对照改)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=038)
本文发布于 2017-08-23 16:42:38,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=038)
环境说明
测试环境:Linux 4.8.0-36-generic #36~16.04.1-Ubuntu SMP Sun Feb 5 09:39:57 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
gcc:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
前言
无
gcc/cpp/c内嵌汇编
内嵌汇编格式和编译器息息相关,对于不同的编译器,有不同的内嵌规则,这里以gcc为例。(此外,基本的一些知识点,我这里就不重复说了,有需要可以去百度相关的东西,此文的面向读者为了解一些汇编知识的人,比如知道一些基本的寄存器等等)
gcc内嵌汇编格式,基本内嵌汇编寄存器等引用为%,带C&&C++的寄存器等引用为%%
__asm__ [__volatile__] ("instruction list");//基本内嵌汇编
__asm__ [__volatile__]("instruction list":Output:Input:Clobber/Modify);//带C&C++相关内容的内嵌汇编
- 以c=a+b为例
在代码段中内嵌汇编
根据第二节的第二种格式,一一对应,就知道,我把a给了ebx,b给了eax,求和后放入eax,把eax传给变量ret
int user_add1(int a, int b){
int ret;
__asm__ __volatile__("movl %2, %%eax;movl %1, %%ebx;addl %%ebx, %%eax;movl %%eax, %0"
:"=m"(ret)
:"m"(a),"m"(b)
:"eax","ebx","memory"
);
return ret;
}
在代码中调用汇编子程序
这里先开辟一个栈帧,然后读到两个传入参数a,b在栈中的位置,并放入寄存器,并对寄存器进行操作求和,函数返回值放在eax中
//xxx.c文件中
c=user_add(a+b);
//xxx.s文件中
.text
.globl user_add
.type user_add, @function
user_add:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
addl %esi, %edi
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
在内嵌汇编代码中调用汇编子程序
由于调用的时候,我先吧参数传给了eax,ebx,通过call,我直接对eax,ebx求和,得到结果
//xxx.c文件中
int ret;
__asm__ __volatile__("movl %2, %%eax;movl %1, %%ebx;call user_add2"
:"=a"(ret)
:"m"(a),"m"(b)
:"ebx","memory"
);
//xxx.s文件中
.text
.globl user_add2
.type user_add2, @function
user_add2:
addl %ebx,%eax
ret
总结与分析
- 首先这是x86下面的汇编指令格式,如果是ARM或者MIPS等平台,请根据各自的指令格式进行修改。
- 这里需要注意的是,从这三种方式来看,前两种方式里面,我们必须要注意,在通过c的方式调用函数时,其参数的存放位置在哪里,参数的存放顺序,同时我们还必须知道gcc的默认调用约定是什么。这是极其重要的
- 第三种方式的调用的最简单粗暴的,但是可能会隐含一些问题,如果gcc没有帮你很好的保护现场,那么可能会出现程序崩溃的情况。
源代码和测试
//t.c
#include <stdio.h>
extern int user_add(int a, int b);
extern int user_add2(int a, int b);
int user_add1(int a, int b){
int ret;
__asm__ __volatile__("movl %2, %%eax;movl %1, %%ebx;addl %%ebx, %%eax;movl %%eax, %0"
:"=m"(ret)
:"m"(a),"m"(b)
:"eax","ebx","memory"
);
return ret;
}
int main(int argc, char *argv[]){
int a = 6;
int b = 3;
printf("user_add1 sum(a+b)=%d\n",user_add1(a,b));
printf("user_add sum(a+b)=%d\n",user_add(a,b));
int ret;
__asm__ __volatile__("movl %2, %%eax;movl %1, %%ebx;call user_add2"
:"=a"(ret)
:"m"(a),"m"(b)
:"ebx","memory"
);
printf("user_add2 sum(a+b)=%d\n",ret);
return 0;
}
//t1.s
.text
.globl user_add
.type user_add, @function
user_add:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
addl %esi, %edi
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.text
.globl user_add2
.type user_add2, @function
user_add2:
addl %ebx,%eax
ret
编译及运行效果:
后记
无
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
GCC&&G++ C && C++ 内嵌汇编和调用汇编函数的方法(x86,ARM自己对照改)的更多相关文章
- ARM GCC 内嵌(inline)汇编手册
转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 百度云:http://pan. ...
- 内嵌的Component调用外部的方法
如果一个内嵌的Component控件需要调用外部定义的方法,用outerDocument.方法名来调用,前提是该方法是public的.如:<mx:DataGridColumn headerTex ...
- ARM GCC 内嵌汇编手册
转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 关于这篇文档这篇文章是本人为方 ...
- GCC 内联汇编(GCC内嵌ARM汇编规则)
转:http://smileleeboo.howbbs.com/posts/list/3127/81062.html 更多文档参见:http://pan.baidu.com/s/1eQ7nd8Q 有时 ...
- Makefile所有内嵌函数
一.文本处理函数以下是GNU make内嵌的文本(字符串)处理函数.1 $(subst FROM,TO,TEXT) 函数名称:字符串替换函数—subst. 函数功能:把字串“TEXT”中的 ...
- redhat6.4 gcc g++ rpm方式安装步骤
centos源 包包自行下载 [root@localhost gcc]# rpm -ivh ppl-0.10.2-11.el6.x86_64.rpm warning: ppl-0.10.2-11.el ...
- python 内嵌函数, 闭包, 函数装饰器
一. 函数内嵌 闭包 在python中,函数可以作为返回值, 可以给变量赋值. 在python中, 内置函数必须被显示的调用, 否则不会执行. #!/usr/bin/env python #-*- ...
- Python3基础 内嵌函数 简单示例
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...
- WebBrowser内嵌页面的跨域调用问题
很早之前我写过一篇Blog:网页通过External接口与WebBrowser交互,文中的交互其实只介绍了JS调用C++的部分,而C++调用JS由于微软自己的例子太多,那篇文章就没介绍,不过我最近遇到 ...
- 【转】WebResource实现在自定义控件中内嵌JS文件
在类库中的资源 其他项目中要使用 需要嵌入才行 参考文献:WebResource实现在自定义控件中内嵌JS文件 1. WebResource简介 ASP.NET(1.0/1.1)给我们提供了一个开发 ...
随机推荐
- 复制对象句柄DuplicateHandle(文件占坑)
DuplicateHandle文档化解释 The DuplicateHandle function duplicates an object handle. The duplicate handle ...
- layui 的tab标签,选项卡的删除,是先切换,后删除,其实这样设计挺好的。
layui的 tab关闭时,是先触发 切换事件,然后再触发删除事件,这一点留意,其实这样设计挺好的.那么留意点,就是先向主进程发送切换消息,然后再向主进程发送删除消息, 这样反而更加有利于,主进程代码 ...
- 二进制安装Kubernetes(k8s)v1.29.2
二进制安装Kubernetes(k8s)v1.29.2 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k ...
- NC50454 A Simple Problem with Integers
题目链接 题目 题目描述 给定数列 \(a[1],a[2], \dots,a[n]\) ,你需要依次进行q个操作,操作有两类: 1 l r x:给定l,r,x,对于所有 \(i \in[l,r]\) ...
- Freaktab将于12月底关闭
出过众多优秀固件的电视盒子论坛Freaktab, 将于2021年12月31日关闭 R.I.P
- springboot jpa自定义SQL查询
说明 在使用JPA实现数据持久化过程中经常会遇到这种情况:我有2张表是一对多的关系,需要通过一个外键ID去关联查询到另外一张表的字段.例如,1张商品表food_info其中存有商品分类ID categ ...
- Spring Boot学生信息管理系统项目实战-1.项目介绍
1.获取源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.项目背景 刚开始自己帮教师朋友写的,核心是学生信息的导入导出功能.后来又扩展了几个模块. 水平一般能力有限,觉着有用的朋友可以拿去自 ...
- spring源码学习之设计模式
目录 1.策略模式 2.观察者模式 3.装饰者模式 4.工厂模式 工厂方法模式 抽象工厂模式 工厂方法和抽象工厂的异同 5.单例模式 6.适配器模式与外观模式 适配器模式 外观模式 7.模板方法模式 ...
- win32 - 以编程方式访问远程计算机上的文件
第一步,在一台计算机上将某个驱动器或者某个文件夹设为sharing模式.这是我们需要访问的共享文件夹.(不需要设置everyone权限) 第二步,我们需要为两台在同一domain下的计算机上建立连接. ...
- [WEB安全] CSRF攻击和防御
一.什么是CSRF 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或 ...