首页 > 编程语言 >vs2022 x64 C/C++和汇编混编 遇到的坑

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

时间:2024-08-12 10:58:37浏览次数:15  
标签:字节 x64 C++ push vs2022 寄存器 堆栈 对齐 指针

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


遇到的问题

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

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

二、问题复现

1.出错代码

代码如下(示例):

capp proc
    sub rsp, 28h             ; 为局部变量和寄存器保存空间

    ; 保存所有需要的寄存器
    push rax
    push rcx
    push rdx
    push r8
    push r9
    push r10
    push r11

    ; 自定义代码
    mov rcx, 10              ; 将参数传递给RCX寄存器
    call hookFunc            ; 调用hookFunc函数

    ; 恢复所有寄存器
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdx
    pop rcx
    pop rax

    add rsp, 28h             ; 恢复堆栈指针
    ret
capp endp

2.问题分析

2.1 堆栈对齐问题

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

3.解决方案

 capp proc
    sub rsp, 28h             ; 为局部变量和寄存器保存空间

    ; 保持堆栈对齐
    sub rsp, 8

    ; 保存寄存器
    push rax
    push rcx
    push rdx
    push r8
    push r9

    ; 调用你的函数
    mov rcx, 10
    call hookFunc

    ; 恢复寄存器
    pop r9
    pop r8
    pop rdx
    pop rcx
    pop rax

    ; 恢复堆栈对齐
    add rsp, 8

    add 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 字节对齐的,所以不需要进行额外的调整。

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

标签:字节,x64,C++,push,vs2022,寄存器,堆栈,对齐,指针
From: https://blog.csdn.net/zsr154278963/article/details/141124499

相关文章

  • C++写文件
    写文件的具体步骤:其中文件打开方式有下面几种:代码实现示例:#include<iostream>usingnamespacestd;#include<fstream>voidtest01(){ ofstreamofs; ofs.open("练习生.txt",ios::out);//这里选择打开自己文件,没有会自己创建 ofs<<"鸡你太美"<<endl; ofs.cl......
  • C++对象的创建(堆和栈的区别)
    在C++中,对象的创建可以在两种不同的内存区域进行:堆(heap)和栈(stack)。这两种内存区域在管理方式、生命周期、性能和使用场景上有所不同。以下是堆和栈上对象创建的主要区别:栈上对象创建:自动内存管理:栈上的对象在创建时自动分配内存,在离开作用域时自动销毁,无需手动管理内存。生命......
  • C++初阶
      目录一.命名空间1.命名空间定义2.命名空间使用二.C++输入&输出三.缺省参数四.函数重载五.引用1.常引用2.传值、传引用效率比较3.引用和指针的区别4.引用和指针的不同点:小知识点:六.内联函数七.auto关键字(C++11)1.auto的使用细则八.基于范围的for循环(C+......
  • C++《类和对象》(上)
    在之前的C++入门基础知识中我们了解了C++的发展过程已经重要性,还初步了解了C++中一些相比C语言特有的知识点,例如命名空间、缺少参数、函数重载、引用等,接下来在本篇中我们将开始C++整个体系中非常重要的一个知识章节——类和对象,类和对象时之后我们更加深入学习C++所必须要学习......
  • 【C++高阶】:特殊类设计和四种类型转换
    ✨                      人生如梦,朝露夕花,宛若泡影   ......
  • C++入门——循环结构2
    重生之你是C++大佬,当你打开这篇博客,竟然发现这点小题简直易如反掌,于是摩拳擦掌,写他个几千行代码。1.找各位数中最大数【问题描述】编写程序找出一个正整数n的各位数字中最大的数字,n由键盘输入。【样例输入】1423【样例输出】4【样例说明】1423有4位数字,分别是1、4、2、3,其......
  • C++入门——循环结构1
    重生之你是C++大佬,当你打开这篇博客,竟然发现这点小题简直易如反掌,于是摩拳擦掌,写他个几千行代码。1.求前N项之和,直至和超过某一值为止【问题描述】已知,计算该序列的前N项和SN,直到SN 大于q为止,q由键盘输入。【输入形式】一个实型数据【输出形式】一个实型数据【样例输入......
  • 洛谷 P1560 [USACO5.2]蜗牛的旅行Snail Trails(c++)
    describe蜗牛在制定今天的旅游计划,有n个景点可选,它已经把这些景点按照顺路游览的顺序排成一排了,每个地方有相应的景观,这里用一个整数表示。蜗牛希望选取连续的一段景点,还要选出来的每一个景点的景观都不同,问它最多能选出多少个景点进行旅游。#include<iostream>#inc......
  • C++提高编程—4、STL常用容器—list(链表)和queue(队列)
    7list容器 7.1基本概念 7.2 构造函数 7.3 赋值和交换 7.4 大小操作  使用10000来填充。7.5 插入与删除 7.6 数据存取 7.7 反转与排序  8set/multset容器 7.1基本概念7.2 构造和赋值7.3大小和交换7.4 插入与删除7.5 查......
  • 【C++算法】双指针
    移动零题目链接:移动零https://leetcode.cn/problems/move-zeroes/description/算法原理这类题是属于数组划分、数组分开题型代码步骤:使用cur遍历数组当cur所指的元素等于0时,cur向后面移动当cur所指的元素不等于0时,dest向后面移动,cur所指元素与dest移动后所指的元素交换当......