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

x64汇编fastcall调用约定

x64汇编环境:只需要在x86基础上对项目属性进行设置,将平台设置为所有平台;

以及在将debug改为x64模式即可:

后续写完代码直接生成项目再使用本地调试器进行运行即可。

fastcall调用约定

在x64架构下,fastcall调用约定是默认的调用约定。它旨在通过寄存器传递参数以提高调用效率。以下是详细的理论说明,涵盖了参数传递、返回值处理、栈管理和寄存器保存规则。

参数传递规则

前四个整数或指针参数通过以下寄存器传递:

  • 第一个参数:RCX

  • 第二个参数:RDX

  • 第三个参数:R8

  • 第四个参数:R9

超过四个的参数通过栈传递,从右到左的顺序依次入栈;即当参数数量超过四个时,第五个及之后的参数按照从右到左的顺序依次压入栈中。

假设有一个函数foo,定义如下:

void foo(int a, int b, int c, int d, int e, int f, int g);

在调用foo(1, 2, 3, 4, 5, 6, 7)时,参数传递顺序如下:

前四个参数通过寄存器传递

  • a(1)传递到RCX

  • b(2)传递到RDX

  • c(3)传递到R8

  • d(4)传递到R9

剩余的参数通过栈传递

  • e(5)

  • f(6)

  • g(7)

在栈中,参数按照从右到左的顺序依次压入栈中,即最右边的参数(g)最先压入栈,接着是f,最后是e。这样,在栈中的顺序如下(从栈顶到栈底):

栈顶 -> g (7)f (6)e (5)
栈底

简单的使用示例

段代码用MASM(Microsoft Assembler)编写的x64汇编代码,包含两个过程(proc):myaddmain;它们实现了一个简单的加法操作,myadd将接收的多个参数相加,而main负责设置这些参数并调用myadd

.code
myadd procxor rax,raxadd rax,qword ptr [rsp + 30h]add rax,qword ptr [rsp + 28h]add rax,r9add rax,r8add rax,rdxadd rax,rcxret
myadd endp
​
main procsub rsp,28hmov qword ptr [rsp + 28h],6mov qword ptr [rsp + 20h],5mov r9,4mov r8,3mov rdx,2mov rcx,1call myaddadd rsp,28hret
main endp
end
代码解释
①main过程

main过程负责设置参数并调用myadd过程:

调整栈指针

  • sub rsp, 28h:调整栈指针,预留40字节(0x28)的栈空间,以对齐栈并为局部变量提供空间。

设置额外参数

  • mov qword ptr [rsp + 28h], 6:将第6个参数6保存到栈上的位置[rsp + 28h]

  • mov qword ptr [rsp + 20h], 5:将第5个参数5保存到栈上的位置[rsp + 20h]

设置寄存器参数

  • mov r9, 4:将第4个参数4存储到r9寄存器。

  • mov r8, 3:将第3个参数3存储到r8寄存器。

  • mov rdx, 2:将第2个参数2存储到rdx寄存器。

  • mov rcx, 1:将第1个参数1存储到rcx寄存器。

调用myadd过程

  • call myadd:调用myadd过程,结果将存储在rax寄存器中。

恢复栈指针

  • add rsp, 28h:恢复栈指针到调用sub rsp, 28h之前的状态。

返回

  • ret:返回,结束程序。

②myadd过程

myadd过程从寄存器和栈中读取6个参数,并将它们相加。具体步骤如下:

初始化累加器

  • xor rax, rax:将rax寄存器清零,作为累加器。

执行加法操作

  • add rax, qword ptr [rsp + 30h]:将参数6(存储在[rsp + 30h])加到rax中。

  • add rax, qword ptr [rsp + 28h]:将参数5(存储在[rsp + 28h])加到rax中。

  • add rax, r9:将参数4(存储在r9寄存器中)加到rax中。

  • add rax, r8:将参数3(存储在r8寄存器中)加到rax中。

  • add rax, rdx:将参数2(存储在rdx寄存器中)加到rax中。

  • add rax, rcx:将参数1(存储在rcx寄存器中)加到rax中。

返回

  • ret:返回,rax寄存器中的结果作为函数返回值。

程序执行结果:

最后RAX寄存器中的值为15h转化为10进制就是21。

x64dbg查看堆栈变化

使用x64dbg进行调试;将程序拖进x64dbg程序中,以下是x64dbg进行调试的四个区域窗口,分别是反汇编、寄存器、内存和堆栈窗口。

刚进来显示的是ntdll.dll的反汇编调试信息,ntdll.dll是Windows操作系统中的一个重要动态链接库(DLL),其全称是NT Layer DLL;这个库包含了许多核心的系统服务和API,直接与Windows NT内核交互。此时要想调试自己的程序可以按下f9单步跳过。

转到自身程序后可以看到两个jmp跳转指令,一个是跳转程序中的入口main,另一个是跳转至自定义过程myadd,接着可以按下f7步进继续执行下一步(f7或者f8需要根据自身x64dbg程序的设置使用),进入main入口点,运行指令。

sub rsp,28h
mov qword ptr [rsp + 28h],6
mov qword ptr [rsp + 20h],5
...
寄存器赋值
...
call myadd

接着往下执行,此时我们对rsp进行查看;转到RSP(查看当前栈顶指针的情况);双击堆栈区并且在堆栈区右击,选择转到rsp即可查看当前rsp的情况:

sub rsp, 28h:调整栈指针,预留40字节(0x28)的栈空间,以对齐栈并为局部变量提供空间;运行此步此时RSP应该在$-28位置,

mov qword ptr [rsp + 28h], 6:将第6个参数6保存到栈上的位置[rsp + 28h]

mov qword ptr [rsp + 20h], 5:将第5个参数5保存到栈上的位置[rsp + 20h]

call myadd:调用myadd过程,结果将存储在rax寄存器中,至此因为使用了call命令,则此时会将函数的返回地址也压入栈内,所以此时RSP在$-30的位置。

继续往下运行进入myadd过程:

xor rax, rax:将rax寄存器清零,作为累加器。

add rax, qword ptr [rsp + 30h]:将参数6(存储在[rsp + 30h])加到rax中。

add rax, qword ptr [rsp + 28h]:将参数5(存储在[rsp + 28h])加到rax中。

...

将rcx、rdx、r8、r9寄存器中的值加入rax中

...

得到最后的结果:

接着进行函数返回,回到入口过程中继续运行;

add rsp, 28h:恢复栈指针到调用sub rsp, 28h之前的状态,此时RSP回到最初的位置。

至此dbg结束。

相关文章:

  • 高阶图神经网络 (HOGNN) 的概念、分类和比较
  • 每月 GitHub 探索|10 款引领科技趋势的开源项目
  • 数学-奇异值
  • STM32通过SPI硬件读写W25Q64
  • MFC GDI绘制卡通人物
  • 长亭网络通信基础
  • LabVIEW、Matlab与Python的比较:从多角度详解三大编程工具
  • 网络安全:Web 安全 面试题.(文件上传漏洞)
  • WPF——属性
  • 案例分享:同为科技与军工项目合作
  • 多层感知器的进化:从基础到并行门控——深入探讨MLP变体的实现、优化与风险
  • 深度解析SD-WAN在企业组网中的应用场景
  • [18] Opencv_CUDA应用之 基于颜色的对象检测与跟踪
  • java -jar
  • 我理解的文本表示模型
  • [Vue CLI 3] 配置解析之 css.extract
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Angular4 模板式表单用法以及验证
  • idea + plantuml 画流程图
  • Javascript编码规范
  • MySQL数据库运维之数据恢复
  • vue脚手架vue-cli
  • 爱情 北京女病人
  • 搭建gitbook 和 访问权限认证
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 服务器从安装到部署全过程(二)
  • 前端路由实现-history
  • 前端面试之CSS3新特性
  • 悄悄地说一个bug
  • 为视图添加丝滑的水波纹
  • 用element的upload组件实现多图片上传和压缩
  • 【干货分享】dos命令大全
  • Spring Batch JSON 支持
  • 整理一些计算机基础知识!
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • #if #elif #endif
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (19)夹钳(用于送货)
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (回溯) LeetCode 78. 子集
  • (四)Linux Shell编程——输入输出重定向
  • (转)创业的注意事项
  • (转)大型网站架构演变和知识体系
  • .gitattributes 文件
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET Core 项目指定SDK版本
  • .Net Core中Quartz的使用方法
  • .Net Winform开发笔记(一)