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

vs2022 x64 C/C++和汇编混编 遇到的坑

vs2022 x64 C/C++和汇编混编 遇到的坑

  • 遇到的问题
  • 二、问题复现
    • 1.出错代码
    • 2.问题分析
      • 2.1 堆栈对齐问题
    • 3.解决方案
  • 总结
      • 奇数和偶数个寄存器的影响
      • 为什么 `sub rsp, 8` 对奇数个寄存器有用?
      • 结论


遇到的问题

0x00007FFFFAE24A29 (msvcp140.dll)处(位于 TestCompileConsoleApp.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
查阅资料发现:异常 0xC0000005: Access Violation 表示程序试图访问一个无效的内存地址。在你的情况下,读取地址 0xFFFFFFFFFFFFFFFF 发生了访问冲突。这通常意味着你试图访问一个无效的指针或未初始化的指针。

— # 一、pandas是什么?
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、问题复现

1.出错代码

代码如下(示例):

capp procsub rsp, 28h             ; 为局部变量和寄存器保存空间; 保存所有需要的寄存器push raxpush rcxpush rdxpush r8push r9push r10push r11; 自定义代码mov rcx, 10              ; 将参数传递给RCX寄存器call hookFunc            ; 调用hookFunc函数; 恢复所有寄存器pop r11pop r10pop r9pop r8pop rdxpop rcxpop raxadd rsp, 28h             ; 恢复堆栈指针ret
capp endp

2.问题分析

2.1 堆栈对齐问题

在 x64 汇编中,函数调用时堆栈指针(RSP)必须是 16 字节对齐的。如果你在调用函数前通过 push 指令保存了寄存器,堆栈指针会减少 8 个字节,这可能会导致堆栈不对齐。

3.解决方案

 capp procsub rsp, 28h             ; 为局部变量和寄存器保存空间; 保持堆栈对齐sub rsp, 8; 保存寄存器push raxpush rcxpush rdxpush r8push r9; 调用你的函数mov rcx, 10call hookFunc; 恢复寄存器pop r9pop r8pop rdxpop rcxpop rax; 恢复堆栈对齐add rsp, 8add rsp, 28h             ; 恢复堆栈指针ret
capp endp

如果保存寄存器的数量是奇数个,可以通过手动调整来保证堆栈对齐。例如,使用 sub rsp, 8 手动调整堆栈指针,使其对齐到 16 字节。


总结

在 x64 汇编中,堆栈的对齐要求是函数调用时堆栈指针(RSP)必须是 16 字节对齐的。为了确保这一点,我们需要根据保存的寄存器数量来决定是否要调整堆栈指针。

奇数和偶数个寄存器的影响

  1. 奇数个寄存器:

    • 每个 push 指令都会将堆栈指针减少 8 个字节
    • 如果你保存奇数个寄存器(例如1、3、5个寄存器),堆栈指针会减少一个不是 16 字节的倍数的值(如 8、24、40 个字节)。
    • 这时,堆栈指针的对齐就会被破坏,从而导致后续函数调用时堆栈不是 16 字节对齐的。
  2. 偶数个寄存器:

    • 如果你保存偶数个寄存器(例如 2、4、6 个寄存器),堆栈指针减少的值会是 16 字节的倍数(如16、32、48个字节)。
    • 在这种情况下,堆栈指针的对齐不会被破坏,因此不需要进行额外的调整。

为什么 sub rsp, 8 对奇数个寄存器有用?

当你保存奇数个寄存器时,堆栈指针被推到一个不是 16 字节对齐的地址。通过在保存寄存器之前执行 sub rsp, 8,你可以先手动将堆栈指针调整到一个不对齐的状态,接下来每次 push 操作都会在最终使堆栈指针回到对齐的状态。

具体来说:

  • sub rsp, 8 手动将 RSP 移动 8 个字节,使其暂时不对齐。
  • 然后,每次 push 操作都会进一步移动 RSP 8 个字节。
  • 如果你总共 push 奇数个寄存器,RSP 将恢复到对齐的状态。

结论

  • 奇数个寄存器: 你需要通过 sub rsp, 8 手动调整堆栈指针,以确保保存和恢复寄存器后堆栈指针是 16 字节对齐的。
  • 偶数个寄存器: 由于堆栈指针在保存和恢复寄存器前后仍然是 16 字节对齐的,所以不需要进行额外的调整。

这个技巧帮助你在函数调用时确保堆栈的对齐性,从而避免潜在的问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • VS2022快速搭建OLLVM
  • 操作系统内存管理技术详解
  • 深入解析 Golang debug/macho 包:解锁 Mach-O 文件的秘籍
  • RPA财务机器人是什么,RPA的具体应用场景有哪些?| 实在RPA研究
  • 量化-均线回归策略
  • ubuntu安装gvm导致cd命令失效
  • Postman入门指南
  • ASP.NET在线交流论坛管理系统
  • QT信号(槽)重载:QProcess、connect、QOverload
  • 基于STM32 HAL库的串口通信实现与应用
  • SpringBoot整合Liquibase
  • Java垃圾收集底层算法实现
  • 【第二节】80x86汇编-寄存器和标志位
  • ios微信分享,微信登录,添加ios平台通用连接Universal Links
  • 【学习笔记】数据结构(五)
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • 2017年终总结、随想
  • AHK 中 = 和 == 等比较运算符的用法
  • C++11: atomic 头文件
  • eclipse的离线汉化
  • ES2017异步函数现已正式可用
  • ES6 ...操作符
  • es6(二):字符串的扩展
  • idea + plantuml 画流程图
  • isset在php5.6-和php7.0+的一些差异
  • JavaScript 基本功--面试宝典
  • Java编程基础24——递归练习
  • magento 货币换算
  • magento2项目上线注意事项
  • Material Design
  • nfs客户端进程变D,延伸linux的lock
  • Sequelize 中文文档 v4 - Getting started - 入门
  • 排序算法学习笔记
  • 浅谈Golang中select的用法
  • 如何在招聘中考核.NET架构师
  • ​补​充​经​纬​恒​润​一​面​
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • # Redis 入门到精通(一)数据类型(4)
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (1)Hilt的基本概念和使用
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (day18) leetcode 204.计数质数
  • (LeetCode) T14. Longest Common Prefix
  • (二)windows配置JDK环境
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (九)One-Wire总线-DS18B20
  • (小白学Java)Java简介和基本配置
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转载)从 Java 代码到 Java 堆
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET IoC 容器(三)Autofac
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题