Step to UEFI (136)哪里来的的 memset

最近编写一个非常简单的代码,遇到奇怪的问题,有兴趣的朋友可以先自己猜一下,答案在后面。
代码如下:

/** @file
    A simple, basic, application showing how the Hello application could be
    built using the "Standard C Libraries" from StdLib.

    Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
    This program and the accompanying materials
    are licensed and made available under the terms and conditions of the BSD License
    which accompanies this distribution. The full text of the license may be found at
    http://opensource.org/licenses/bsd-license.

    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Library/BaseLib.h>
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/EfiShell.h>
#include <Library/ShellLib.h>

void prt(IN UINT16 *p)
{
       UINT8   i;
        for (i=0;i<256;i++) {
           Print(L"%c",*p);
           p++;
        }
}
INTN
EFIAPI
ShellAppMain (
  IN UINTN Argc,
  IN CHAR16 **Argv
  )
{
        CHAR8   buffer[256];
        UINT16  i;
        
        for (i=0;i<256;i++) {
                buffer[i]='L';
        }
        prt((UINT16*)buffer);
        return 0;
}

 

错误信息如下:

"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\x86_amd64\li
b.exe" /NOLOGO /LTCG /OUT:d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\App
lications\SimpleDemo\SimpleDemo\OUTPUT\wft.lib @d:\udk2017\Build\AppPkg\DEBUG_VS
2013x86\X64\AppPkg\Applications\SimpleDemo\SimpleDemo\OUTPUT\object_files.lst
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\x86_amd64\li
nk.exe" /OUT:d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\Sim
pleDemo\SimpleDemo\DEBUG\wft.dll /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OP
T:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /
DLL /ENTRY:_ModuleEntryPoint /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BAS
E:0 /DRIVER /DEBUG @d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applicat
ions\SimpleDemo\SimpleDemo\OUTPUT\static_library_files.lst
Generating code
Finished generating code
UefiApplicationEntryPoint.lib(ApplicationEntryPoint.obj) : error LNK2001: unreso
lved external symbol memset
d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\SimpleDemo\Simpl
eDemo\DEBUG\wft.dll : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 12.0
\Vc\bin\x86_amd64\link.exe"' : return code '0x460'
Stop.

build...
: error 7000: Failed to execute command
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\nmake.exe /no
logo tbuild [d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\Sim
pleDemo\SimpleDemo]

build...
: error F002: Failed to build module
d:\udk2017\AppPkg\Applications\SimpleDemo\SimpleDemo.inf [X64, VS2013x86
, DEBUG]

- Failed -
Build end time: 11:17:59, Dec.12 2017
Build total time: 00:00:12

上面就是完整的代码和现象,有兴趣的朋友可以琢磨一下,答案在下面。

 

kenan

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

刚开始看到错误提示我还非常疑惑”为啥没有具体错误信息“。仔细观察才发现错误信息是无法Link到 memset上。但是我的代码没有调用 memset。带着疑惑,我在 Inf 中刚加入 /FAcs /Od 准备查看汇编级代码。但是加入之后错误就会消失。
[BuildOptions]
MSFT:*_*_X64_CC_FLAGS = /FAcs /Od
再仔细研究,原来是 /Od 会让错误消失,接下来就简单了,比较只有 /FAcs 和带有 /Od的汇编代码,在 Simpledemo.cod 文件中找到了答案。左边是没有加入 /Od 的,右边是加入 /Od 的。这个参数的意思是关闭优化。比较打开和关闭优化的结果:

mms

因此,问题就清楚了,因为我的赋值是对 buffer[] 全部写入 “L”,所以编译器会自作主张的用memset 来对内存直接赋值,但是恰好我们没有定义 memset,所以就会出现错误。

《Step to UEFI (136)哪里来的的 memset》有12个想法

  1. 這問題剛好之前遇到 ,之前百思不得其解
    那時最後for迴圈還改寫成 每個array值一一給予
    感謝版主 現在懂了

    1. 我用的就是 vs2015 。 我记得之前看过 uefi 的编译设置,会设定“不使用编译器自带的库”,所以即使 vs 自定义了 memset 也是不会使用的。

      1. include 头文件有用吗?照理来说这是 link 阶段发生的事情,头文件里面应该只是一些宏和函数原型,生成的 obj 文件里面似乎不会提示哪些库被用到?

  2. 最近看了一些memory function的源码,有些地方是这样描述的:
    //
    // Declare the local variables that actually move the data elements as
    // volatile to prevent the optimizer from replacing this function with
    // the intrinsic memset()
    //
    volatile UINT8 *Pointer;

    变量声明volatile, 以防止这种情形的典范,有好几处都是这样子描述的,大伙可以搜一下。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注