如果你在Shell下直接使用 Float 或者 Double 在编译的时候会遇到这样的问题
Architecture(s) = IA32
Build target = DEBUG
Toolchain = VS2008
Active Platform = c:\edk2\Nt32Pkg\Nt32Pkg.dsc
Flash Image Definition = c:\edk2\Nt32Pkg\Nt32Pkg.fdf
Processing meta-data ... done!
"C:\Program Files\Microsoft Visual Studio 9.0\Vc\bin\link.exe" /out:"c:\edk2\Build\NT32\DEBUG_VS2008\IA32\SecMain.exe" /base:0x10000000 /pdb:"c:\edk2\Build\NT32\DEBUG_VS2008\IA32\SecMain.pdb" /LIBPATH:"C:\Program Files\Microsoft Visual Studio 9.0\VC\Lib" /LIBPATH:"C:\Program Files\Microsoft Visual Studio 9.0\VC\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MSVCRTD.lib Gdi32.lib User32.lib Winmm.lib Advapi32.lib /EXPORT:InitializeDriver=_ModuleEntryPoint /ALIGN:4096 /FILEALIGN:4096 /SUBSYSTEM:CONSOLE @c:\edk2\Build\NT32\DEBUG_VS2008\IA32\Nt32Pkg\Sec\SecMain\OUTPUT\static_library_files.lst
LINK : warning LNK4108: /ALIGN specified without /DRIVER; image may not run
LINK : warning LNK4001: no object files specified; libraries used
Creating library c:\edk2\Build\NT32\DEBUG_VS2008\IA32\SecMain.lib and object c:\edk2\Build\NT32\DEBUG_VS2008\IA32\SecMain.exp
Generating code
Finished generating code
"C:\Program Files\Microsoft Visual Studio 9.0\Vc\bin\link.exe" /OUT:c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\DEBUG\FloatTest.dll /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /MACHINE:X86 /LTCG /DLL /ENTRY:_ModuleEntryPoint /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG /EXPORT:InitializeDriver=_ModuleEntryPoint /ALIGN:4096 /FILEALIGN:4096 /SUBSYSTEM:CONSOLE @c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\OUTPUT\static_library_files.lst
Creating library c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\DEBUG\FloatTest.lib and object c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\DEBUG\FloatTest.exp
Generating code
Finished generating code
c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\DEBUG\FloatTest.dll : warning LNK4086: entrypoint '__ModuleEntryPoint' is not __stdcall with 12 bytes of arguments; image may not run
FloatTest.lib(floattest.obj) : error LNK2001: unresolved external symbol __fltused
c:\edk2\Build\NT32\DEBUG_VS2008\IA32\MdeModulePkg\Application\floattest\floattest\DEBUG\FloatTest.dll : fatal error LNK1120: 1 unresolved externals
我baidu和google之后得到的大概的结论是:UEFI 替换了Link中的默认库(CRT.LIB?),但是因为MS的编译器存在一个bug,所以导致仍然使用部分的默认库,所以导致这样的问题【这个解释存疑,不确定】。至于解决方法,经过我的实验确认就是使用 EADK 库【参考1】。我的理解是这个库是用来替代标准C库编写EDKII程序的,因此Float之类在其中也有重新定义。
加入方法:
1.解压EADK,然后将其中三个目录放到你EDK2的根目录下
2.修改 Nt32Pkg.dsc 加入红色部分
#
# Misc
#
DebugLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
DebugPrintErrorLevelLib|MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
#LABZ_Start
SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
LibC|StdLib/LibC/LibC.inf
LibStdLib|StdLib/LibC/StdLib/StdLib.inf
LibString|StdLib/LibC/String/String.inf
LibWchar|StdLib/LibC/Wchar/Wchar.inf
LibCType|StdLib/LibC/Ctype/Ctype.inf
LibTime|StdLib/LibC/Time/Time.inf
LibStdio|StdLib/LibC/Stdio/Stdio.inf
LibGdtoa|StdLib/LibC/gdtoa/gdtoa.inf
LibLocale|StdLib/LibC/Locale/Locale.inf
LibUefi|StdLib/LibC/Uefi/Uefi.inf
LibMath|StdLib/LibC/Math/Math.inf
LibSignal|StdLib/LibC/Signal/Signal.inf
LibNetUtil|StdLib/LibC/NetUtil/NetUtil.inf
#LABZ_End
[LibraryClasses.common.USER_DEFINED]
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
OemHookStatusCodeLib|Nt32Pkg/Library/PeiNt32OemHookStatusCodeLib/PeiNt32OemHookStatusCodeLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
3. floattest.inf 中必须加入下面2个
[LibraryClasses]
UefiApplicationEntryPoint
UefiLib
PcdLib
ShellCEntryLib
ShellLib
LibMath
LibC|
下面就可以在你的代码中放心大胆的使用Float了。
一个计算 Pi 的Shell Application
#include <Library/UefiLib.h> #include <Library/ShellCEntryLib.h> // // Based on code found at http://code.google.com/p/my-itoa/ // int Integer2AsciiString(int val, char* buf) { const unsigned int radix = 10; char* p = buf; unsigned int a; int len; char* b; char temp; unsigned int u; if (val < 0) { *p++ = '-'; val = 0 - val; } u = (unsigned int)val; b = p; do { a = u % radix; u /= radix; *p++ =(char) a + '0'; } while (u > 0); len = (int)(p - buf); *p-- = 0; // swap do { temp = *p; *p = *b; *b = temp; --p; ++b; } while (b < p); return len; } // // Based on code found on the Internet (author unknown) // Search for ftoa implementations // int Float2AsciiString(float f, char *buffer, int numdecimals) { int status = 0; char *s = buffer; long mantissa, int_part, frac_part; short exp2; char m; typedef union { long L; float F; } LF_t; LF_t x; if (f == 0.0) { // return 0.00 *s++ = '0'; *s++ = '.'; *s++ = '0'; *s++ = '0'; *s = 0; return status; } x.F = f; exp2 = (unsigned char)(x.L >> 23) - 127; mantissa = (x.L & 0xFFFFFF) | 0x800000; frac_part = 0; int_part = 0; if (exp2 >= 31 || exp2 < -23) { *s = 0; return 1; } if (exp2 >= 0) { int_part = mantissa >> (23 - exp2); frac_part = (mantissa << (exp2 + 1)) & 0xFFFFFF; } else { frac_part = (mantissa & 0xFFFFFF) >> -(exp2 + 1); } if (int_part == 0) *s++ = '0'; else { Integer2AsciiString(int_part, s); while (*s) s++; } *s++ = '.'; if (frac_part == 0) *s++ = '0'; else { for (m = 0; m < numdecimals; m++) { // print BCD frac_part = (frac_part << 3) + (frac_part << 1); // frac_part *= 10 *s++ = (frac_part >> 24) + '0'; frac_part &= 0xFFFFFF; } } *s = 0; return status; } VOID Ascii2UnicodeString(CHAR8 *String, CHAR16 *UniString) { while (*String != '\0') { *(UniString++) = (CHAR16) *(String++); } *UniString = '\0'; } //PI= 4- /3+4/5-4/7+4/9 EFI_STATUS EFIAPI CalcPI() { char str[8]; static CHAR16 wstr[8]; int i; float g1 = (float) 1; float g2 = (float) 0; for (i=0;i<100;i++) { if (i%2==0) {g2=g2+ 4/ g1;} else {g2=g2-4/ g1;} Float2AsciiString(g2, str, 4); Ascii2UnicodeString(str, wstr); Print(L" PI: %s\n", wstr); g1=g1+2; } return EFI_SUCCESS; } EFI_STATUS EFIAPI UefiMain(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { CalcPI(); return EFI_SUCCESS; }
运行结果:
示例代码下载 floattest
参考:
1.http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=EDKII_EADK
EDK II Application Development Kit for include the Standard C Libraries in UEFI Shell Applications