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

【第48节】探究汇编使用特性:从基础到混合编程

目录

引言

 一、调用约定的奥秘

1.1 . C调用约定(_cdecl)

1.2 stdcall调用约定(_stdcall)

1.3  fastcall快速调用约定(_fastcall)

1.4 thiscall调用约定(C++类成员函数)

二、X64汇编的独特魅力

三、裸函数的特殊用途

四、X64混合编程的实践

4.1 环境设置与项目搭建

4.2 代码编写与调用


引言

        在编程的广阔世界里,汇编语言以其独特的地位和强大的功能,为开发者提供了深入硬件底层、优化性能的有力手段。今天,让我们一起通过具体的代码例子,深入了解汇编使用的一些特性。

 一、调用约定的奥秘

1.1 . C调用约定(_cdecl)

// 01调用约定.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"//1.c调用方式 :从右到左入栈,函数外部平衡堆栈
int _cdecl fun_cdecl(int a,int b)
{return a + b;
}

        在C调用约定中,参数从右到左依次压入栈中,而堆栈的平衡是在函数外部进行的。这意味着调用函数的代码需要负责清理堆栈,这样的设计使得可变参数函数(如printf)成为可能,因为调用者知道参数的个数,可以准确地清理堆栈。

1.2 stdcall调用约定(_stdcall)

//2.stdcall windowsAPI调用约定 :从右到左入栈,函数内部平衡堆栈 : ret 8
int _stdcall fun_stdcall(int a, int b)
{return a + b;
}

        stdcall调用约定常用于Windows API函数。同样,参数从右到左入栈,但与_cdecl不同的是,堆栈的平衡是在函数内部完成的。函数返回时使用“ret 8”指令,这里的8表示参数占用的字节数,自动清理堆栈,减轻了调用者的负担,提高了代码的执行效率。

1.3  fastcall快速调用约定(_fastcall)

//3.fastcall快速调用约定 :从右到左入栈,函数内部平衡堆栈
int _fastcall fun_fastcall(int a, int b,int c,int d )
{return a + b+c+d;
}

        fastcall快速调用约定为了进一步提高性能,它会尽可能地将参数放入寄存器中传递,减少栈操作的开销。参数同样从右到左入栈,并且在函数内部平衡堆栈。对于一些对性能要求极高的函数,这种调用约定能显著提升运行速度。

1.4 thiscall调用约定(C++类成员函数)

//4.this c++调用约定    从右到左入栈,函数内部平衡堆栈
class OBJ {
public:int  fun_thiscall(int a, int b, int c, int d){return a + b + c + d;}int m_number;
};

        在C++类的成员函数中,使用thiscall调用约定。除了参数从右到左入栈和函数内部平衡堆栈外,它还有一个特殊之处,即通过this指针来访问对象的成员变量。this指针隐含地作为第一个参数传递,让成员函数能够知道它是被哪个对象调用的。

代码整合:

// 01调用约定.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"//1.c调用方式 :从右到左入栈,函数外部平衡堆栈
int _cdecl fun_cdecl(int a,int b)
{return a + b;
}//2.stdcall windowsAPI调用约定 :从右到左入栈,函数内部平衡堆栈 : ret 8
int _stdcall fun_stdcall(int a, int b)
{return a + b;
}//3.fastcall快速调用约定 :从右到左入栈,函数内部平衡堆栈 
int _fastcall fun_fastcall(int a, int b,int c,int d )
{return a + b+c+d;
}//4.this c++调用约定    从右到左入栈,函数内部平衡堆栈
class OBJ {
public:int  fun_thiscall(int a, int b, int c, int d){return a + b + c + d;}int m_number;
};int main()
{//1.c调用方式//fun_cdecl(1, 2);//2.stdcall windowsAPI调用约定//fun_stdcall(1, 2);//3.fastcall快速调用约定//fun_fastcall(1, 2,3,4);//4.this c++调用约定OBJ obj;obj.fun_thiscall(1, 2, 3, 4);return 0;
}

二、X64汇编的独特魅力

X64函数调用

// 02x64汇编.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"//x64函数调用
long long fun(long long a, long long b, long long c, long long d, long long x)
{return a + b + c + d + x;}int main()
{//64位调用fun(0x1, 0x2, 0x3, 0x4, 0x5);return 0;
}

        在64位环境下,X64汇编有着自己独特的函数调用规范。例如,在这个函数中,参数通过特定的寄存器传递,这与32位环境下主要通过栈传递参数有所不同。这种方式减少了栈操作,提高了函数调用的效率,对于处理大量数据和高性能计算的场景尤为重要。

三、裸函数的特殊用途

裸函数与普通函数的区别

// 03裸函数.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"//裸函数 编译器不做任何优化
void _declspec(naked) fun1()
{_asm mov eax,99_asm ret}//普通函数
void fun2()
{//会添加开辟栈帧
}int main()
{//1.裸函数函数调用fun1();//2.普通属性fun2();return 0;
}

        裸函数通过`_declspec(naked)`声明,它告诉编译器不对函数进行任何常规的优化和代码生成,比如不会自动生成开辟和清理栈帧的代码。在`fun1`函数中,我们直接使用汇编指令`mov eax, 99`和`ret`,完全掌控函数的执行流程。而普通函数`fun2`,编译器会自动添加开辟栈帧等常规操作,虽然方便但在某些对性能和代码体积要求苛刻的场景下可能不够灵活。

四、X64混合编程的实践

4.1 环境设置与项目搭建

(1)要进行X64混合编程,首先需要将VS的编译环境设置为X64,然后添加一个function.asm的文件用于编写汇编代码。接着要对项目属性和文件属性进行一系列设置。
(2)设置项目属性:如图所示,需要进行特定的配置,确保项目能够正确处理汇编代码。

(3)设置文件属性:对function.asm文件的属性也需要调整,以便编译器能够正确识别和处理汇编代码。

4.2 代码编写与调用

        在function.asm文件中编写汇编代码,比如实现一个简单的两数取最大值的方法:

.code            ; 代码段开始; 函数功能:比较两个整数并返回较大值
; 参数:
;   rcx - 第一个整数参数
;   rdx - 第二个整数参数
; 返回值:rax 寄存器存储两个参数中的较大值
Max procmov rax, rcx        ; 将第一个参数的值存入 rax 寄存器cmp rax, rdx        ; 比较 rax 和 rdx 的值jge _ge             ; 如果 rax 大于等于 rdx,跳转到 _ge 标签处
_le:mov rax, rdx        ; 如果 rax 小于 rdx,将第二个参数的值存入 rax 寄存器
_ge:ret                 ; 返回 rax 中的值(即较大值)
Max endpEND                 ; 汇编源文件结束

        在源文件中,通过`extern "C"`声明外部函数,防止C++的名称粉碎机制导致链接错误:因为被c++名称粉碎机制糟蹋后,链接器就会报无法解析的外部符号的错误。.asm文件的函数名没有经过名称粉碎机制的。

#include "stdafx.h"//声明函数
extern"C" int Max( int left , int right );int main()
{//调用汇编函数int a =Max(5, 6);return 0;
}

        通过这样的方式,我们实现了C++与汇编语言的混合编程,充分发挥了两种语言的优势,既利用了汇编语言的高效性和对硬件的直接控制能力,又结合了C++的高级特性和便捷的编程方式。

        汇编语言的这些特性为我们提供了丰富的编程手段,无论是优化性能、深入底层开发,还是进行混合编程,都能帮助我们更好地完成各种复杂的任务,在不同的编程场景中发挥出独特的价值,值得开发者们深入学习和探索。

 

相关文章:

  • 合成数据中的对抗样本生成与应用:让AI模型更强、更稳、更安全
  • 算法驱动光场革命:SLM技术引领智能光学新时代
  • 【面经】杭州产链数字科技一面
  • 嵌入式音视频开发指南:从MPP框架到QT实战全解析
  • 《Operating System Concepts》阅读笔记:p735-p737
  • vscode的一些使用技巧记录
  • 在 Jetpack Compose 中实现 iOS 风格输入框
  • Zenodo上传文件流程
  • 安卓手机万能遥控器APP推荐
  • Git 解决“Filename too long”问题
  • Java学习笔记--多态:多态的介绍,多态的基本使用,多态的条件下成员的访问特点,多态的好处
  • 【科研绘图系列】R语言绘制多个气泡图组合图(bubble plot)
  • k8s 调整Node节点 Max_Pods
  • Linux网络编程 深入解析TFTP协议:基于UDP的文件传输实战
  • 三大等待和三大切换
  • PP-OCR的安卓端部署
  • Google Colab测试部署Qwen大模型,实现PDF转MD场景OCR 识别(支持单机环境)
  • CSS3笔记
  • 设计模式 --- 外观模式
  • 基于FPGA的AES加解密系统verilog实现,包含testbench和开发板硬件测试
  • 吕治国执掌全国唯一的热带海洋大学,曾从教育部“空降”海南
  • 3月赴美外国游客数量加速下滑
  • “中国电三之都”江苏丰县成功举办第十五届电动车展览会
  • 因在罗博特科并购项目中执业违规,东方证券、国浩所均遭警示
  • 加力扩围支持消费品以旧换新,江苏要送出1800万元彩票
  • 中央刚提级巡视,昆明2人宣告被查