汇编:内联汇编和混合编程

2024-06-16 06:12
文章标签 编程 汇编 混合 内联

本文主要是介绍汇编:内联汇编和混合编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C/C++内联汇编

C/C++ 内联汇编(Inline Assembly)是一种在C或C++代码中嵌入汇编语言指令的方法,以便在不离开C/C++环境的情况下利用汇编语言的优势进行性能优化或执行特定的硬件操作。以下是一些详细的说明和示例,展示如何在C和C++代码中使用内联汇编:

创建新的控制台项目,将C/C++代码生成的运行库更换为多线程调试(/MTD)。在C++开发中,运行库(Runtime Library)是执行程序时所依赖的库,它提供了标准C和C++函数的实现,如输入输出、内存管理等。MTD(Multi-Threaded Debug):静态链接。程序在编译时将运行库静态地嵌入到可执行文件中,生成一个独立的可执行文件;除此之外还要确保同窗口下的Spectre缓解被禁用;

设置完成后就可在C/Cpp源代码文件中进行代码编写,以下是一个简单示例(脱裤子放屁版):

代码示例展示了在C++程序中使用内联汇编来调用一个C++函数,并将结果存储在一个全局变量中,这种方法展示了如何在内联汇编中传递参数并调用C++函数。

#include <iostream>
​
int nNumber = 20;
int myadd(int a, int b) {return a + b;
}
​
int main()
{__asm {xor eax,eaxmov eax,nNumberpush eaxxor eax,eaxmov eax,10push eaxcall myaddmov nNumber,eaxadd esp,8}std::cout << nNumber << std::endl;
}
内联汇编代码

寄存器初始化和使用

  • xor eax, eax 将EAX寄存器置0,这是一种常见的快速清零方式。

  • mov eax, nNumber 将全局变量 nNumber 的值移动到EAX寄存器中。

  • push eax 将EAX的值压入堆栈,这是函数调用约定的一部分,用于传递参数。

参数传递和函数调用

  • mov eax, 10 将立即数10移动到EAX寄存器中。

  • push eax 将EAX的值压入堆栈。这两个 push 操作将参数 nNumber10 压入堆栈,顺序为右到左,即 myadd(10, nNumber)

  • call myadd 调用 myadd 函数,函数的返回值将存储在EAX寄存器中。

结果处理和堆栈恢复

  • mov nNumber, eax 将函数 myadd 的返回值赋值给全局变量 nNumber

  • add esp, 8 恢复堆栈指针,这是为了平衡 push 操作,8 字节是两个 int 参数的大小。

运行后的结果:

C/C++&汇编混合编程

x64架构程序不适配上述内联汇编的语法,将debug改为x64再重新生成该代码会发现报错:

那么在x64架构下,若是需要在C或C++代码中嵌入汇编语言指令,可以使用混合编程的方式进行代码嵌入;混合编程(Mixed Programming)是指在一个软件项目中结合使用多种编程语言或编程范式,以便利用各自的优势来实现更高效、更灵活的应用。

首先需要在C/C++源码文件下创建.asm文件,接着将我们需要用到的汇编代码写入.asm文件中,接着需要在C/C++源码中对需要用到的汇编代码(过程)进行声明即可;以下是一个简单的示例:

项目文件
source.asm      MixCode.cpp     
source.asm代码:

实现了一个简单的加法函数myadd,接受两个参数,将它们相加,并返回结果。

.code
myadd procxor rax,raxsub rsp,28hadd rax,rdxadd rax,rcxadd rsp,28h
myadd endp
end
代码解释:

xor rax, rax 是一种快速清零寄存器 RAX 的方式。

sub rsp, 28h 调整栈指针 rsp,为函数调用创建一个栈帧,在64位模式下,栈需要16字节对齐,这里调整40字节以对齐栈。

add rax, rdx 将第一个参数(RDX 寄存器中的值)加到 RAX 中。

add rax, rcx 将第二个参数(RCX 寄存器中的值)加到 RAX 中。

add rsp, 28h 恢复栈指针 rsp,撤销之前的调整。

ret 指令从函数返回,将控制转移回调用点。

MixCode.cpp代码:
#include <iostream>
​
int nNumber = 20;
​
extern "C" long long myadd(long long llNumber_A, long long llNumberB); //声明函数
​
int main()
{long long resNumber = myadd(nNumber, 10);std::cout << resNumber << std::endl;system("pause");
}
C++和汇编的集成

变量声明int nNumber = 20; 声明了一个全局变量 nNumber,初始值为20。

外部函数声明extern "C" long long myadd(long long llNumber_A, long long llNumber_B); 告诉编译器 myadd 是一个C函数(使用C的调用约定),并接受两个long long参数,返回一个long long值。

调用汇编函数long long resNumber = myadd(nNumber, 10); 调用 myadd 函数,传入 nNumber10,将返回值赋给 resNumber

输出结果std::cout << resNumber << std::endl; 输出结果到控制台。

程序执行结果:

这篇关于汇编:内联汇编和混合编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1065663

相关文章

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域,结合了生物学、计算机科学和统计学。随着高通量测序技术的发展,海量的生物数据需要通过编程来进行处理和分析。因此,掌握生信编程技能,成为每一个生物信息学研究者的必备能力。 生信代码入门,旨在帮助初学者从零开始学习生物信息学中的编程基础。通过学习常用

rtmp流媒体编程相关整理2013(crtmpserver,rtmpdump,x264,faac)

转自:http://blog.163.com/zhujiatc@126/blog/static/1834638201392335213119/ 相关资料在线版(不定时更新,其实也不会很多,也许一两个月也不会改) http://www.zhujiatc.esy.es/crtmpserver/index.htm 去年在这进行rtmp相关整理,其实内容早有了,只是整理一下看着方

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern