使用 MSVC 工具生成裸机二进制文件的过程是什么?

What is the process for generating a bare metal binary with MSVC tools?

使用 MSVC 工具生成裸机二进制文件的过程是什么?

在 GNU 领域,您 cc 编译或 as assemble 源代码到 object 文件,ld link object 文件到 ELF(使用 linker 脚本),然后 objcopy ELF 中的相关部分作为“固件二进制文件”。我想做同样的事情,但只使用 MSVC 提供的工具。

我一直在使用以下 ARM64 startup.s 进行测试:

 AREA .text, CODE, READONLY
start
 LDR w1, =0xDEADBEEF
 B .
 END

这是假设简单地用0xDEADBEEF加载X1寄存器的低32位然后自旋。要assemble代码我运行:

armasm64.exe startup.s

我猜如果我有一个 peripherals.c 源文件,我需要 link startup.speripherals.c 到一个单一的可执行文件(COFF ?,PE?)。最后,我需要去掉 any COFF/PE headers 以便 ARM MCU 可以在加载时执行代码。

免责声明:我不属于我的专业领域,我根据我使用 MSVC 工具所做的一些测试提出了一个答案,在阅读了一些 Microsoft 文档之后,在提出问题三天后,还没有提出任何答案。我希望这个答案会引发更多知情的答案,这样我就可以很乐意收回它。

“使用 MSVC 工具生成裸机二进制文件的过程是什么?”问题的答案。可能是:“有 none”。

aarch64-pe.asm:

 AREA .text, CODE, READONLY
 EXPORT start
start
 LDR w1, =0xDEADBEEF
 B .
 END

(符号 'start' 需要使用 EXPORT 指令创建 public 才能被 linker 解析。

组装:

armasm64.exe aarch64-pe.asm

现在,aarch64(版本 14.28.29334.0)的 linker 只支持有限的目标子系统列表:

BOOT_APPLICATION,
CONSOLE,
WINDOWS,
NATIVE,
POSIX,
EFI_APPLICATION, EFI_BOOT_SERVICE_DRIVER, EFI_ROM, EFI_RUNTIME_DRIVER

从 Microsoft 和 EFI 文档来看,似乎所有这些子系统都需要一个能够理解 PECOFF 格式或能够 运行 进入 BCD WMI Provider 环境的加载器BOOT_APPLICATION 子系统的情况。

没有“BAREMETAL”子系统这样的东西。 当尝试 link aarch64-pe.obj 每个子系统但 EFI_ROM 使用 0x0000000040000000 作为基地址时, linker 退出显示相同的错误,抱怨起始地址不能小于4GiB:

D:\opt\msvc\arm64>for %I in (BOOT_APPLICATION CONSOLE WINDOWS NATIVE POSIX EFI_APPLICATION EFI_BOOT_SERVICE_DRIVER EFI_ROM EFI_RUNTIME_DRIVER) do link /entry:start /BASE:0x0000000040000000 /subsystem:%I aarch64-pe.obj

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:BOOT_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:CONSOLE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:WINDOWS aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:NATIVE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:POSIX aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_BOOT_SERVICE_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_ROM aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : warning LNK4075: ignoring '/BASE' due to '/SUBSYSTEM:EFI_ROM' specification

D:\opt\msvc\arm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_RUNTIME_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

这可能是裸机嵌入式系统的问题,或者这可能需要 MMU 可用并且已经由...配置的裸机程序从起始地址开始禁用 MMU,起始地址小于4GiB.

当 运行ning dumpbin.exe against aarch64-pe.efi 时,基地址似乎设置为 0000000180000000 因为 ldr 指令位于0x0000000180001000,文件类型设置为 DLL

dumpbin.exe  /disasm aarch64-pe.efi
File Type: DLL

  0000000180001000: 18000041  ldr         w1,0000000180001008
  0000000180001004: 14000000  b           0000000180001004
  0000000180001008: DEADBEEF

  Summary

        1000 .rdata
        1000 .text

当对 linker 以 0x0000000100000000 作为基地址生成的可执行文件执行 dumpbin.exe 时,文件类型始终是 EXECUTABLE IMAGE.

更重要的是,dumpbin.exe 似乎也不提供将生成的可执行文件转换为标准格式,例如 s-recordintel hex

因此,我的结论是,MSVC 工具单独暂时不允许构建 aarch64 裸机应用程序。