如何阻止MSVC将自定义Set_Memory替换为memset且保留其他优化?
解决MSVC优化替换自定义内存设置函数为memset的问题
针对你遇到的问题,以下是几个不丢失全局优化的解决办法:
方法1:用volatile修饰指针破坏编译器模式识别
修改自定义函数,给目标指针加上volatile限定,强制编译器执行每一次内存赋值操作,无法将循环替换为memset调用:
void Set_Memory(VOID* Dest, UINTN Len, CHAR8 Val) { volatile UINT8* ptr = (volatile UINT8*)Dest; for (UINTN i = 0; i < Len; ++i) { ptr[i] = Val; } }
注意:UINTN是EDK2的类型,需确保头文件已正确引入,避免用int作为循环变量(Len是UINTN,类型不匹配可能导致潜在问题)。
方法2:局部禁用全局优化指令
在自定义函数前后添加MSVC编译指令,仅对该函数禁用会替换循环为标准库函数的全局优化,其他函数保持原有优化级别:
#pragma optimize("g", off) void Set_Memory(VOID* Dest, UINTN Len, CHAR8 Val) { for (UINTN i = 0; i < Len; ++i) { ((UINT8*)Dest)[i] = Val; } } #pragma optimize("g", on)
"g"选项对应MSVC的全局优化,关闭后编译器不会将可识别的内存操作替换为标准库函数调用。
方法3:用汇编实现内存设置函数
直接用汇编编写Set_Memory,完全避免编译器的优化干预,同时保证执行效率与memset一致:
x86平台汇编实现
.code Set_Memory proc push ebp mov ebp, esp mov ecx, [ebp+12] ; 传入的Len参数 mov al, [ebp+16] ; 传入的Val参数 mov edi, [ebp+8] ; 传入的Dest参数 rep stosb ; 重复将al中的值写入edi指向的内存,共ecx次 pop ebp ret Set_Memory endp end
x64平台汇编实现
.code Set_Memory proc ; x64调用约定:RCX=Dest, RDX=Len, R8=Val mov rcx, rcx ; 目标地址存入RCX mov rdx, rdx ; 长度存入RDX mov al, r8b ; 填充值存入AL rep stosb ; 执行内存填充 ret Set_Memory endp end
将汇编代码保存为.asm文件,添加到项目中编译即可。
内容的提问来源于stack exchange,提问作者EatingTechnobladesRemainsAt3am
相关产品推荐
相关产品推荐

