MSVC平台下X64 ABI规则

LLVM-MSVC:在Windows内核驱动开发中融合LLVM与MSVC优势 编译器是软件开发的核心工具,负责将高级语言代码转换为机器可执行的指令。在Windows平台,MSVC编译器凭借其与操作系统的深度集成,成为内核驱动和系统级开发的主流选择,但其相对封闭的生态和有限的扩展性有时难以满足高级定制需求。LLVM/Clang作为开源、模块化的现代编译器框架,提供了强大的优化能力和可定制性,但其默认遵循GCC/Itanium ABI,与MSVC的语法和ABI存在显著差异。llvm-msvc项目通过构建一个MSVC兼容层,巧妙地将LLVM的先进特性引入Windows开发环境,实现了对MS 阅读详情

目录

1. X64调用规则概述

2. 开启X64优化

2.1 优化选项说明

2.2 Visual Studio开发环境中设置这个编译选项

3. 类型和存储

3.1 标量类型(Scalar types)

3.2 聚合类型(Aggregates types)和联合类型(Union type)

3.2.1 数组

3.2.2 结构

3.2.3 联合

3.3 结构对齐示例(以C代码示例)

3.4 位域(Bitfields)

4. 与X86编译器的冲突

5. X64寄存器用法

6. X64内存栈的用法

6.1 X64内存栈的分配

6.2 X64内存动态参数栈区域构建

6.3 函数类型

6.4 malloc对齐

6.5 alloca函数

7. prolog(序言)和epilog(完结)

8 X64异常处理

9 内置(intrinsic)和内联(inline)汇编

10 X64映像格式


本节描述X64架构(X86架构的64位扩展)的基本应用程序二进制接口(Application Binary Interface,简记为ABI)。这个主题的内容包括函数调用规则、类型分布、栈和寄存器用法、以及其它内容。

1. X64调用规则概述

    X64与X86之间重要的两个区别是64位的寻址能力和一套平坦的16个16位通用寄存器。给定扩展的寄存器集,X64使用 __fastcall调用规则和基于RISC(Reduced Instruction Set Computer)的异常处理模型。__fastcall调用规则采用寄存器来传递被调函数的前4个参数,以及采用栈空间传递被调函数的超出4个以外的参数。关于X64函数调用规则,包括寄存器的使用、栈参数、返回值、以及栈的解开(stack unwinding),参见X64调用约定。

2. 开启X64优化

2.1 优化选项说明

    下面的编译选项可以帮助你优化你写的X64代码:

/favor (对具体架构的优化):该选项生成针对特定架构或 AMD 和 Intel 架构中的微架构细节进行优化的代码。

语法形式:/favor:{blend | ATOM | AMD64 | INTEL64}

说明:

/favor:blend

(x86和x64)生成的代码针对AMD 和 Intel 架构中的微架构细节进行了优化。虽然 /favor:blend可能无法在特定处理器上提供最佳性能,但它旨在为各种 x86 和 x64 处理器提供最佳性能。 默认情况下,/favor:blend 有效。

/favor:ATOM

(x86 和 x64)生成的代码针对Intel Atom处理器和Intel Centrino Atom处理器技术的细节进行了优化。使用 /favor:ATOM生成的代码还可以为Intel处理器生成Intel SSSE3、SSE3、SSE2 和 SSE 指令。

/favor:AMD64

(仅限 x64)为支持 64 位扩展的AMD Opteron和Athlon处理器优化生成的代码。优化后的代码可以在所有 x64 兼容平台上运行。使用/favor:AMD64 生成的代码可能会导致支持Intel64的Intel处理器的性能下降。

/favor:INTEL64

(仅限 x64)为支持Intel64的Intel处理器优化生成的代码,这通常会为该平台带来更好的性能。 生成的代码可以在任何 x64 平台上运行。使用 /favor:INTEL64 生成的代码可能会导致AMD Opteron和支持64位扩展的Athlon处理器的性能下降。

注:Intel64架构以前称为Extended Memory 64 Technology,对应的编译器选项是/favor:EM64T。

2.2 Visual Studio开发环境中设置这个编译选项

(1) 打开项目的属性页对话框。细节请参见在Visual Studio中设置C++编译和构建属性文档部分。

(2) 选择配置属性-> C/C++ -> 命令行 属性页。

(3) 在附加选项框中输入编译选项。

3. 类型和存储

    本节描述X64架构各种数据类型及相对应的存储。

3.1 标量类型(Scalar types)

    尽管可以以任何对齐方式访问数据,但是为了避免性能损失,我们仍推荐在内存的自然边界或多个自然边界上对齐访问数据。枚举是一个常量整数,按32位整数对待。下表描述了数据的类型定义和建议的存储,因为它适合使用以下值对齐:

字节(Byte)——8位

字(Word)——16位

双字(Doubleword)——32位

四字(Quadword)——64位

八字(Octadword)——128位

标量类型

C语据类型

存储大小(按字节)

推荐对齐

INT8(8位整数,下同)

char

1

字节

UINT8

unsigned char

1

字节

INT16

short

2

字

UINT16

unsigned short

2

字

INT32

int,long (注:在64位环境下,windows都占4个字节;但linux下int占4字节,long占8字节)

4(注:linux平台下long占8字节)

双字(注:若long占8个字节,对应方式应为四字)

UINT32

nt,long (注:在64位环境下,windows都占4个字节;但linux下unsinged int占4字节,unsigned long占8字节)

4(注:linux平台下unsigned long占8字节)

双字(注:若unsigned long占8个字节,对应方式应为四字)

INT64

__int64(linux下自定义为long long)

8

四字

UINT64

Unsigned __int64(linux下自定义为unsigned long long)

8

四字

FP32(浮点精度)

float

4

双字

FP64(浮点精度)

double

8

四字

POINTER

*

8

四字

__m64

struct __m64

8

四字

__m128

struct __m128

16

八字

3.2 聚合类型(Aggregates types)和联合类型(Union type)

    其它数据类型,例如,数组、结构、联合,都有严格的对齐要求,以确保聚合类型和联合类型以地址连续的方式存取。下面是数组、结构、联合的定义:

3.2.1 数组

    包含一组有序的相邻数据对象。每个对象称为一个元素。数组内的所有元素都具有相同的大小和数据类型。

3.2.2 结构

    包含一组有序的数据对象。与数组不同的是,结构内的数据对象可以有不同的数据类型和大小。每个结构内的对象称为一个成员。

3.2.3 联合

    包含一组命名成员中的任何一个的对象。这个命名集合的成员可以是任何类型。系统为联合类型分配的存储空间等于存储联合的最大成员所要求的空间大小,再加上按对齐要求所需的填充空间的大小。

下表展示了对联合和结构这种标量类型存储所强烈建议的对齐字节数:

标量类型

C语据类型

存储大小(按字节)

要求对齐

INT8(8位整数,下同)

char

1

字节

UINT8

unsigned char

1

字节

INT16

short

2

字

UINT16

unsigned short

2

字

INT32

int,long (注:在64位环境下,windows都占4个字节;但linux下int占4字节,long占8字节)

4(注:linux平台下long占8字节)

双字(注:若long占8个字节,对应方式应为四字)

UINT32

nt,long (注:在64位环境下,windows都占4个字节;但linux下unsinged int占4字节,unsigned long占8字节)

4(注:linux平台下unsigned long占8字节)

双字(注:若unsigned long占8个字节,对应方式应为四字)

INT64

__int64(linux下自定义为long long)

8

四字

UINT64

Unsigned __int64(linux下自定义为unsigned long long)

8

四字

FP32(浮点精度)

float

4

双字

FP64(浮点精度)

double

8

四字

POINTER

*

8

四字

__m64

struct __m64

8

四字

__m128

struct __m128

16

八字

下面的聚合类型适用的对齐规则:

(1) 一个数组的对齐与一个数组的元素中的某一个元素的对齐相同。

(2) 结构或联合开头的对齐方式是任何单个成员的最大对齐方式。结构或联合中的每一个成员必须放置在前面列表中定义的合适的对齐位置,对齐规则可能会要求隐式的内部填充,这取决于前一个成员的大小。

(3) 结构体的大小必须是其对齐字节的整数倍大小,系统可能会要求在其最后的成员之后对不足长度的部分进行填充。由于结构和联合可以分组到数组中,因此结构或联合的每个数组元素必须以先前确定的正确对齐方式开始和结束。

(4) 只要按照先前确定的对齐规则,以大于对齐所需的最小存储空间存储数据是有可能的(注:也就是说,以恰好的大小对齐内存边界,不浪费内存,即没有填充字节,这是理想的情况;出现所需空间大于这个理想空间是可能的,因为定义成员的顺序不一样,按规则所需的空间大小也不一样)。

(5) 单个编译器可能会出于大小原因调整结构的打包。例如/Zp(结构成员对齐)允许调整结构的打包。

3.3 结构对齐示例(以C代码示例)

(1) 示例1

// 总大小 = 2 字节, 对齐字节= 2 字节(word).

_declspec(align(2)) struct {

    short a;      // +0; size = 2 字节(+0,表示其上一个元素的位置,下同)

}

示意图:

(2) 示例2

// 总大小 = 24 字节, 对齐字节= 8 字节(quadword).

_declspec(align(8)) struct {

    int a;       // +0; size = 4 字节

    double b;    // +8; size = 8 字节(前面a不够8字节,用4个字节填充,+8开始)

    short c;     // +16; size = 2 字节

}

示意图:

3) 示例3

// 总大小 = 12 字节, 对齐字节= 4 字节(doubleword).

_declspec(align(4)) struct {

    char a;       // +0; size = 1 字节

    short b;      // +2; size = 2字节

    char c;       // +4; size = 1字节

    int d;        // +8; size = 4字节

}

示意图:

(4) 示例4

// 总大小 = 8 字节, 对齐字节= 8 字节(quadword).

_declspec(align(8)) union {

    char *p;      // +0; size = 8字节 (指针当整数对待,64位平台指针点8字节)

    short s;      // +0; size = 2字节

    long l;       // +0; size = 4字节 (linux平台下为8)

}

示意图:

 

3.4 位域(Bitfields)

结构位域限定在64位之内,可以是类型signed int,unsigned int,int64,或unsigned int64。跨越类型边界的位域将跨过边界位将位对齐到下一个类型的对齐边界。例如,整数位域不能跨越32位的边界。

4. 与X86编译器的冲突

当你使用X86编译器编译一个应用程序的时候,大于4字节的数据类型不会自动地对齐于栈的边界。因为X86编译器是一个4字节的对齐栈,任何大于4字节的数据类型,例如64位整数,不会自动地对齐于8字节的地址。

运行带有非对齐数据的程序有两方面的影响:

(1) 相对于访问对齐数据的内存地址,访问非对齐数据的内存地址会消耗更长的时间。

(2) 非对齐数据的内存地址不能用于自旋锁的操作(interlocked operations)。

如果你要求严格的数据对齐,可以在声明变量时使用声明符号__declspec(align(N))。这会促使编译器动态对齐栈以满足你的对齐规范要求。然而,在程序运行时动态调整栈对齐可能会拖慢程序的运行速度。

5. X64寄存器用法

X64架构提供了16个通用寄存器(以下简称整型寄存器)以及16个XMM/YMM浮点寄存器。易失性寄存器(volatile registers)是调用者认为在调用函数过程中会被销毁的暂存寄存器(scratch registers)。非易失性寄存器(nonvolatile registers)要求在调用函数期间保留其值,并且,如果被调函数修改了其值,也必须事先保存下来,完成后将其恢复。

下面的表描述了在函数调用的时候如何使用每个寄存器——寄存器易失性和保存:

寄存器

状态

用法

RAX

Volatile

返回值值存器

RCX

Volatile

第1个整型参数

RDX

Volatile

第2个整型参数

R8

Volatile

第3个整型参数

R9

Volatile

第4个整型参数

R10:R11

Volatile

必须由调用函数根据需要保存; 在 syscall/sysret 指令中使用

R12:R15

Nonvolatile

必须由被调函数保存

RDI

Nonvolatile

必须由被调函数保存

RSI

Nonvolatile

必须由被调函数保存

RBX

Nonvolatile

必须由被调函数保存

RBP

Nonvolatile

可作为栈帧指针; 必须由被调函数保存

RSP

Nonvolatile

栈指针

XMM0, YMM0

Volatile

第1个浮点数参数;当使用__vectorcall 时用于传递第1个向量类型参数

XMM1, YMM1

Volatile

第2个浮点数参数;当使用__vectorcall 时用于传递第2个向量类型参数

XMM2, YMM2

Volatile

第3个浮点数参数;当使用__vectorcall 时用于传递第3个向量类型参数

XMM3, YMM3

Volatile

第4个浮点数参数;当使用__vectorcall 时用于传递第4个向量类型参数

XMM4, YMM4

Volatile

必须由被调函数保存; 当使用__vectorcall 时用于传递第5个向量类型参数

XMM5, YMM5

Volatile

必须由调用函数保存; 当使用__vectorcall 时用于传递第6个向量类型参数

XMM6:XMM15, YMM6:YMM15

Nonvolatile (XMM), Volatile (upper half of YMM)

必须由被调函数保存。 YMM寄存器必须由调用函数根据需要保存。

在函数退出和函数进入 C 运行时库调用和 Windows 系统调用时,预期会清除掉CPU 标志寄存器中的方向标志位。

6. X64内存栈的用法

所有RSP的当前地址之外的内存都被认为是易失性的:操作系统或者调试器可能会在用户调试会话期间、或者中断处理期间,重写这些内存。因此,在试图使用RSP读取数据或将数据写入栈帧之前,总是必须先设置RSP,使之指向一块有效的栈帧地址。下面讨论用于局部变量的栈空间的分配内置alloca函数(alloca intrinsic)。

6.1 X64内存栈的分配

一个函数的序言(prolog)对为局部变量、寄存器值、栈参数、以及寄存器参数的临时存储而分配栈空间的这种行为负责。

参数区域总是位于栈底(即使调用alloca函数也是如此),因此,在调用任何函数期间,它总是比邻函数调用完成后的返回地址。它至少包括4个条目(实际上还包括返回地址),但实践中总是为任何可能调用的函数传递需要的参数分配足够的空间用于存储所有的参数。需要指出的是,即使函数参数永远不会位于栈的开头(即栈底),系统也始终会为寄存器参数的传递分配空间(甚至0个寄存器,这块栈空间仍然会被保留,即所谓“影子内存”);系统一定会确保被调函数参数所需的所有空间都被分配到位。要求寄存器参数使用起始址,是因为可以获得一块连续的区域,以便被调函数需要参数列表(va_list)或者某个参数的地址时可以提供。这块区域也为形实转换(thunk execution)期间存储寄存器参数提供了一个便利的存储位置,并且作为一个调试选项(例如,假如将参数存储在序言代码的起始位置,它就使得在调试的时候,很容易找到参数)。即使被调函数的参数少于4个,这4个栈的位置也属于被调函数,除了存储寄存器参数值,也可以被被调函数用于其它目的。因此,调用函数在调用别的函数期间,不可以在这块栈空间中存储信息(影子内存)。

假如空间是动态分配(例如,使用函数alloca分配),则必须使用非易失性寄存器作为帧指针来标记堆栈固定部分的基址,并且必须在prolog中保存和初始化该寄存器。需指出,当使用alloca的时候,在内一个调用函数中调用同一个被调函数,可以使用不同的栈首地址传递它们的参数。

栈空间总是保持16字节边界对齐,prolog例外(例如,在返回地址之后入栈),以及用于某些帧函数类型标明函数类型(Function Types)的场合例外。

下图是一个函数A调用一个非叶函数B (a non-leaf function B)的栈分布示例。函数A的prolog已经为所有寄存器分配了空间。B要求的栈参数位于栈底。调用函数压入返回地址到栈上,而B的prolog为其局部变量、非易失性寄存器、以及其进一步地调用其它函数分配存储空间。假如B使用了alloca,则分配的空间位于局部变量/非易失性寄存器存储区域和参数栈区域之间。如下图所示:

当B进一步调用另一个函数的时候,其返回地址被压入RCX起始地址的正下方。

6.2 X64内存动态参数栈区域构建

假如使用了栈指针,则存在动态创建参数堆栈区域的选项。目前在X64 编译器中没有这样做。

6.3 函数类型

存在两种基本的函数类型。要求栈帧的函数称为帧函数(frame functions),和不要求栈帧的函数称为叶函数(leaf functions,叶子节点,没有更下面的子叶了)。

帧函数分配栈空间、调用其它函数、存储非易失性寄存器的值、或者使用异常处理。也要求一个函数表条目(a function table entry)。帧函数要求prolog和epilog。帧函数可以动态分配栈空间,并且可以使用一个帧指针。一个帧函数具备这个调用标准在其处理上的全部能力。

假如一个帧函数没有调用另一个函数,则其不要求对齐栈空间(参见栈分配的文档)。

叶函数不要求函数表条目。它不会改变任何非易失性寄存器的值,包括RSP在内,意味着它不会调用任何函数,也不会分配任何栈空间(注:即,叶函数名称的特点所在)。当执行的时候,允许它在没对齐的情况下离开栈空间。

6.4 malloc对齐

叶函数可以确保返回合适的对齐内存,以便于存储任何这样的对象——它们要求满足基本内存对齐要求,并且系统又可以为这样的对象分配合适的内存(也就是说,如果内存要求过多,则系统不能满足)。基本内存对齐是指,在没有对齐规范的情况下,小于或者等于系统实现所支持的最大对齐字节数。(在VC++要求按double类型或者按8字节对齐。在面向64位平台的代码中,要求按照16字节对齐。) 例如,4字节的内存分配会对齐在一个支持任何4字节或者更小字节对象的边界对齐(注:实际上,小于4字节的数据,也分配4字节的存储空间,不足部分用字节填充)。

C++允许扩展对齐(extended alignment)类型(也称为溢出对齐(over-alignment)类型)。例如,SSE的_m128和_m256类型,以及使用__declspec(align( n ))符号修饰的类型(其中n大于8,具有扩展类型)。malloc不保证适合要求使用扩展对齐的对象在内存边界对齐。要为益出类型分配内存,请使用_aligned_malloc及其相关函数。

6.5 alloca函数

_alloca函数要求16字节对齐且还要求使用帧指针。

分配的栈需要在其后面包含用于后续调用函数的参数的空间,正如6.1栈分配部分所述。

7. prolog(序言)和epilog(完结)

分配栈空间、调用其它的函数、保存非易失性寄存器、或者使用异常处理的的每一个函数,都必须要有一个prolog(这个prolog的地址限制在与相应函数表条目相关的unwind数据(解开数据)中描述)和在每次在退出函数时都必须要有一个epilog。关于在X64平台所要求的prolog和epilog代码,请求见X64 prolog和epilog说明文档。

8 X64异常处理

有关用于在X64上实现结构化异常处理和C++异常处理行为的约定和数据结构的信息,请参阅 X64 异常处理文档。

9 内置(intrinsic)和内联(inline)汇编

X64编译器的限制之一是不支持内联汇编程序。这意味着不能用C或C++编写的函数要么必须编写为子例程,要么编写为编译器支持的内置函数。某些功能对性能敏感,而其他功能则不是。性能敏感函数应该作为内置函数来实现。

编译器支持的内置函数请参见编译器内置函描述文档。

10 X64映像格式

    X64可执行映像是PE32+格式。可执行映像(包括DLL和EXE)严格限定在2G大小以内,因此,带有32位位移的相对地址可以用于静态映像数据的寻址。这些数据包括导入地址表(import address table)、字符常量、静态全局数据、等等。

资料来源:

x64 ABI conventions | Microsoft DocsLearn more about: x64 ABI conventionshttps://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-170

跨平台ABI战争:从MSVC到GCC的二进制兼容性博弈 本文深入探讨了跨平台开发中MSVC、GCC和Clang编译器间的ABI(应用二进制接口)兼容性问题,揭示了二进制兼容性的核心挑战与解决方案。通过分析内存布局、名称修饰和异常处理等关键差异,提供了PIMPL模式、稳定C接口和版本化设计等实战策略,帮助开发者构建真正跨编译器的二进制组件。 阅读详情

相关推荐

MinGW与MSVC混用指南:ABI差异与DLL兼容性解析

在Windows上进行C/C++开发时,二进制兼容性始终是绕不开的难题。编译器生成的代码不仅要遵循语法规范,还必须符合底层ABI(Application Binary Interface)约定,包括函数调用约定、符号修饰规则、结构体对齐方式以及异常处理机制。当MinGW与MSVC这两套主流工具链相遇,其各自独立的ABI体系导致静态库几乎无法通用,而动态库在纯C接口与x64环境下则存在有限兼容的可能。理解这些差异,可以帮助开发者快速判断第三方库的可用性,避免链接报错与运行期崩溃的风险。无论是集成SDK、发布跨

weixin_32187037的博客 293

C/C++ ABI以及如何对动态连接库加载一个C++成员函数符号

介绍C与C++编程语言的ABI,并描述如何对动态连接库加载一个C++中一个类的成员函数符号

zenny_chen的专栏 1624

QT 5.12.12 + MSVC2017 ABI对齐实战指南

Qt是跨平台C++应用开发的核心框架,MSVC则是Windows原生编译的关键工具链。当选择长期支持(LTS)版本Qt 5.12.12与Visual Studio 2017组合时,其技术价值不仅在于稳定性与兼容性,更在于满足军工、工控等高可靠性场景对ABI二进制接口严格一致性的硬性要求。该组合规避了新版Qt短期支持带来的维护风险,也避免了MSVC2019+在老旧Win7嵌入式系统上常见的0xc000007b运行时错误。典型应用场景包括国军标GJB-5000A认证软件、工业现场设备配套系统及需十年构建可复现的

weixin_34015336的博客 317

x64不同平台的调用约定

x64的ABI在Unix(Linux,Mac OS)上和Windows上是不同的,调用约定有区别。wikipedia上对调用约定的解释调用约定的不同(寄存器传参部分)

u011553241的博客 1143

Rust on Windows:从 MSVC 到 MinGW,我为什么最终又回到了 MSVC 的怀抱?

本文探讨了在Windows平台上使用Rust开发时,MSVC与MinGW工具链的选择问题。通过对比两者的历史渊源、兼容性挑战、调试体验和性能优化,作者最终回归MSVC工具链,并分享了配置实践。文章深入分析了`x86_64-w64-mingw32-gcc`等错误,帮助开发者做出更明智的选择。

djfiew7234的博客 636

Qt Creator集成ThunderOpenSDK:MSVC ABI匹配与Release构建实战

在跨平台应用开发中,Qt Creator凭借高效的UI构建能力和丰富的控件库,成为众多C++工程师的首选框架。然而,当引入第三方原生SDK时,开发者最先撞见的往往不是业务逻辑,而是编译器之间“无声的战争”:MSVC与MinGW的C++ ABI不兼容。ABI定义了函数调用约定、名称修饰规则、异常处理机制与运行时库版本,直接决定了代码能否在二进制层面正常协作。MSVC生成的.lib导入库无法被MinGW的链接器识别,这也是Qt工程中大量undefined reference的常见根源。理解Qt构建套件体系,选择

weixin_28681255的博客 175

避坑指南:在VS2019中使用CMake编译libwebsockets 4.0时遇到的5个常见问题及解决方案

本文详细解析了在VS2019环境中使用CMake编译libwebsockets 4.0库时,关于OpenSSL版本兼容性、路径配置、zlib链接、CMake生成器选择以及运行时库冲突这5个最常见问题的成因与解决方案。重点指导如何正确配置OpenSSL 1.1.x依赖,并提供清晰的命令行操作与项目设置步骤,帮助开发者高效完成编译,顺利集成高性能WebSocket功能。

yolo5detector的博客 203

Windows x64汇编实战:ABI、API调用与调试

计算机底层开发中,指令集架构决定了程序如何与硬件交互,而函数调用约定则是高级语言与机器码之间的桥梁。x64架构下,寄存器数量和位宽大幅扩展,但随之而来的是更严格的参数传递规则和栈管理要求。理解Microsoft x64 ABI中的寄存器传参、影子空间和栈对齐机制,是编写稳定汇编代码的关键。无论是进行性能优化、系统编程还是安全研究,掌握这些底层原理都能帮助开发者更精确地控制执行流程。围绕Windows x64环境,从环境搭建到API调用,逐步解析ml64汇编器下的调用约定实践,并通过数组求和、弹窗程序等示例,

weixin_33226548的博客 181

MSVC平台下X64处理器函数调用规则——底层机制

目录 1. 默认的调用规则 2. 内存边界对齐问题 3. 解开性(Unwindability) 4. 参数传递 5. 可变数量参数的传递 6. 非原型函数 7. 函数返回值 8. 调用函数或被调函数存储寄存器 9. 函数指针 10. 对较旧代码的浮点支持 11. 浮点状态和控制寄存器(Float Point Status and Control Register,简记为FPSCR) 12. 多媒体扩展控制和状态寄存器(Multimedia Extensions Control and

ComputerInBook的专栏 1617

DRACO编译完成的库怎么用?Win10+MSVC2019 x64接入与避坑指南

3D模型压缩是点云处理、glTF优化和AR/VR资源分发的关键环节,Google开源的Draco通过顶点坐标量化与预测编码,将三角网格数据压缩为紧凑比特流,大幅降低存储与传输成本。在Windows平台用C++集成Draco时,源码编译常因CMake生成器、运行库配置或ABI不匹配而失败,因此预编译的DRACO库(win10+MSVC2019-64)成为高效选择。本文围绕这份现成库,介绍如何验收文件清单、用CMake接入MSVC2019工程、通过draco_encoder/decoder验证压缩链路,并总结链

weixin_42554151的博客 185

CMake 3.14.2-win64-x64:OpenCV 4.5.x 编译的 ABI 锁定关键版本

CMake 是跨平台构建系统的核心工具,其版本与编译器ABI、目标架构及第三方库(如 OpenCV)存在强耦合关系。CMake 3.14 引入了对 C++17 特性(如 target_compile_features)和 Windows SDK 10.0+ 的稳定支持,成为 OpenCV 4.5.x 系列强制依赖的最小版本;而 win64-x64 后缀则决定了 CMAKE_SIZEOF_VOID_P=8,确保与 x64 构建环境及 opencv_world.dll 的二进制兼容性。该版本不兼容 VS2022

weixin_30096975的博客 95

C++逆向核心:this指针、虚表劫持与MSVC/GCC ABI识别

C++逆向工程中,对象模型是理解二进制代码的关键。this指针作为成员函数的隐藏参数,其传递方式在不同架构与编译器下差异显著:Windows x64使用rcx,Linux采用rdi。虚表(vtable)是实现多态的核心机制,其内存布局与劫持技术直接影响安全研究和漏洞分析。同时,MSVC与GCC在符号修饰、RTTI、异常处理等方面留下鲜明ABI指纹,掌握这些特征可快速判断工具链。本文结合实践,从this指针定位、虚表劫持到编译器识别,系统梳理C++逆向的基础方法论,帮助分析者高效重建对象模型。

weixin_31856057的博客 279

msvc2010_x64.rar

QT5.5官方没有提供64位的编译版本,所以自己编译了一个64版本。 如何编译可以参考 https://blog.youkuaiyun.com/xiao503/article/details/51576425

详细解析API和ABI的区别

API(Application Programming Interface)和ABI(Application Binary Interface)是软件开发中的两个关键概念,分别作用于源代码和二进制代码层面。API是开发者编写代码时使用的接口,定义了函数名、参数类型和返回值等逻辑规则。而ABI则规定了编译后的二进制代码如何与操作系统或其他库交互,涉及参数传递、寄存器使用等底层规则。两者的兼容性对程序运行至关重要:API变化会导致编译错误,而ABI变化则可能导致运行时崩溃。API通常由开发者直接使用,而ABI则

2504_91948029的博客 2001

超声波 vs 红外 vs 激光雷达:扫地机器人避障传感器选型指南(实测对比)

本文深入对比了扫地机器人三种主流避障传感器——超声波、红外与激光雷达的核心原理与实测表现。文章基于成本、精度、环境适应性等关键指标,提供了清晰的选型决策树和典型场景配置方案,旨在帮助开发者与爱好者根据项目需求与预算,构建高效可靠的机器人避障系统。

h0i1j2k3l的博客 690

ROS2实战:打造智能巡检机器人的关键技术与实现

本文详细介绍了基于ROS2和Navigation2构建智能巡检机器人的完整实战流程。通过设计主从协作的事件驱动架构,实现了机器人在已知地图中的自动导航、定点语音播报和环境图像采集功能。文章涵盖了从环境搭建、仿真配置到核心控制节点、语音服务与图像记录模块的代码实现,为开发者打造实用的自动巡检机器人提供了清晰的技术指南。

weixin_29031057的博客 223

《UEFI内核导读》UEFI Application Binary Interface (ABI)简介

不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误,支持可变参数的函数。编译器,有类似的机制,区别在于使用不同的寄存器来传递参数和返回值。所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。,其他类型的参数根据参数类型不同其传递方式稍有不同,如下表。个参数使用寄存器传递,从第五个开始使用堆栈传递,例如,拥有。调用约定仅在输出函数名前加上一个下划线前缀,如,原函数为。寄存器,而不是通过堆栈来传递,同样函数返回值通过。不会要求调用者传递参数数量,

业余电子爱好者的日常 1766

F28335 DSP ePWM模块实战:从基础配置到电机控制

本文详细解析了TI TMS320F28335 DSP的ePWM模块,从基础概念、寄存器配置到实战应用。通过代码示例,手把手教你如何配置定时中断、生成PWM波形、实现死区保护与故障联防,并最终完成一个可调速、可换向的直流电机控制项目,是掌握F28335电机控制核心技术的实战指南。

g5h6i的博客 1128

STL 仓库贡献指南:从 CLA 到 ABI 兼容的 MSVC 标准库开发全流程

本篇技术指南围绕 MSVC C++ 标准库(STL)仓库的 [CONTRIBUTING.md](https://link.gitcode.com/i/9f04c18c165cb9ea6311fdb5b071bed9) 展开,系统讲解如何参与这一标准库项目的开发:从签署 CLA、选择入门 Issue,到提交与审查 Pull Request,再到必须遵守的标识符命名、ABI 兼容与代码来源三大硬性约束

gitblog_01198的博客 381

飞书应用开发脚手架lark-harness:从零构建企业级机器人

在构建企业级应用时,开发脚手架是提升工程效率和规范性的关键工具。其核心原理在于通过预设的项目模板、最佳实践和通用模块封装,自动化处理项目初始化、配置管理和基础架构搭建。这种技术价值在于将开发者从重复性劳动中解放出来,确保团队技术栈统一,并降低维护成本。在Node.js生态中,脚手架常与Express或Koa等Web框架结合,用于快速构建Web服务、API接口和实时事件处理系统。具体到飞书开放平台开发场景,开发者需要处理OAuth 2.0授权、事件订阅验证、消息加解密等复杂且标准的流程。lark-harnes

weixin_30703911的博客 612

YOLOv10有效涨点专栏目录 | 包含卷积、主干、检测头、注意力机制、Neck、二次创新、独家创新等上百种创新机制

Hello,各位读者们好本专栏自开设以来已经更新改进教程100余篇其中包含二次创新、独家创新多种改进方法,包含C2f、主干、检测头、注意力机制、Neck多种结构,也有损失函数和一些细节点上的创新。同时本人一些讲解视频和包含我所有创新的YOLOv10文档并不能在优快云上传,通过建立交流群的形式在内上传我完整的文件和视频我也会在群内不定期和大家交流回答大家问题。专栏介绍。

Snu77的博客 1万+

MinGW vs MSVC:深度全方位对比指南

选择MSVC,就是选择了一条舒适、强大但封闭的 Windows 原生高速公路。你拥有最好的工具、最全的文档和最深的系统集成,但必须遵守微软的规则,且难以脱离 Windows 生态。选择MinGW,就是选择了一把灵活、通用且自由的瑞士军刀。它让你用熟悉的 GCC 命令在 Windows 上工作,轻松实现跨平台,但在处理 Windows 特有深水区功能时会遇到一些摩擦,且需要自己解决 ABI 隔离问题。在 2026 年的今天,专业的大型 Windows 软件开发依然首选 MSVC,而。

浩瀚之水的专栏 765

OpenClaw实战系列03:Slack/Telegram国际版接入实战指南

在当今的软件开发和工作流自动化中,将项目管理工具与即时通讯平台集成已成为提高团队协作效率的关键。OpenClaw作为一个开源的自动化工具,通过接入Slack和Telegram国际版,可以实现实时通知、自动化任务触发和团队协作的无缝对接。本文将详细介绍如何实现OpenClaw与这两个主流即时通讯平台的集成。OpenClaw是一个开源的自动化工作流引擎,支持多种触发器和执行器,能够帮助开发团队实现CI/CD流程、任务调度、监控告警等自动化场景。模块化设计:支持插件化扩展多触发器支持。

PeterPan的博客 587
上一篇: MSVC平台下X64处理器函数调用规则——底层机制
下一篇: MSVC环境下X64 prolog和epilog
ComputerInBook
博客等级 码龄19年 1168粉丝 464原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值