You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 01:52:34