构建最少的汇编代码会产生空的二进制文件

building minimal piece of assembly code produces empty binary file

我正在尝试为我的 MCU(tms570lc4357zwt、ARM Cortex-R5f)构建一个最小的启动代码,但是当我构建它并将其转换为二进制格式时,生成的大小 。 bin 文件为 0.

测试文件的结构是:

test
  +--CMakeLists.txt
  +--gnu.cmake
  +--isr.S
  +--linker.ld

我使用的工具版本是:

这是我的最小汇编代码 (isr.S):

.arm

.global isr_vector
.global bootloader

.section .flash_code_isr_vector
isr_vector:
    LDR     pc, = bootloader /* reset. */
    LDR     pc, = 0x08000004 /* undefined instruction. */
    LDR     pc, = 0x08000008 /* system call. */
    LDR     pc, = 0x0800000C /* prefetch abort. */
    LDR     pc, = 0x08000010 /* data abort. */
    LDR     pc, = 0x08000014 /* reserved. */
    LDR     pc, = 0x08000018 /* IRQ. */
    LDR     pc, = 0x0800001C /* FIQ. */

.section .flash_code_bootloader
bootloader:
    B       .

我使用以下链接描述文件 (linker.ld):

MEMORY
{
    FLASH_TCM (rx) : ORIGIN = 0x00000000, LENGTH = 4M
    RAM_TCM (rwx) : ORIGIN = 0x08000000, LENGTH = 512K
    RAM_ECC (rwx) : ORIGIN = 0x08400000, LENGTH = 512K
}

ENTRY(isr_vector)

SECTIONS
{
    .flash_code_isr_vector 0x00000000 :
    {
        KEEP(*(.flash_code_isr_vector))
    } > FLASH_TCM

    .flash_code_bootloader 0x00000100 :
    {
        *(.flash_code_bootloader)
    } > FLASH_TCM
}

下面是我用来构建它的工具链文件 (gnu.cmake) 和 cmake 文件 (CMakeLists.txt):

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

set(CMAKE_C_COMPILER_WORKS TRUE)

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

find_program(ASM_COMPILER arm-none-eabi-gcc)
find_program(C_COMPILER arm-none-eabi-gcc)
find_program(LINKER arm-none-eabi-gcc)
find_program(ARCHIVER arm-none-eabi-ar)
find_program(RANLIB arm-none-eabi-ranlib)

set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
set(CMAKE_C_COMPILER ${C_COMPILER})
set(CMAKE_C_LINK_EXECUTABLE ${LINKER})
set(CMAKE_AR ${ARCHIVER})
set(CMAKE_RANLIB ${RANLIB})

add_compile_options(-mbig-endian
    -march=armv7-r
    -Wall
    -Wextra)

add_link_options(-mbig-endian
    -nostdlib
    -Wall
    -Wextra)
cmake_minimum_required(VERSION 3.0)

project(test VERSION 0.0.1 LANGUAGES ASM)

add_executable(isr.elf isr.S)
add_compile_options(isr.elf PRIVATE -O0 -g)
set_target_properties(isr.elf PROPERTIES
    LINK_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")

add_custom_target(isr.bin
    DEPENDS isr.elf
    COMMAND arm-none-eabi-objcopy -O binary isr.elf isr.bin
    WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

add_custom_target(isr.asm
    DEPENDS isr.elf
    COMMAND arm-none-eabi-objdump -D isr.elf > isr.asm
    WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

add_custom_target(isr.size
    DEPENDS isr.elf
    COMMAND arm-none-eabi-size isr.elf -A -t -x
    WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})

问题可以通过 运行 重现(在包含所有文件的文件夹中)mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../gnu.cmake

问题来了: 当我询问 .elf 的大小时(调用 isr.size 目标),我得到

isr.elf  :
section                  size    addr
.flash_code_isr_vector   0x40     0x0
.flash_code_bootloader    0x4   0x100
.ARM.attributes          0x1d     0x0
Total                    0x61

这似乎是合理的。现在当我生成 .bin 文件(调用 isr.bin 目标)时,生成的文件大小为 0。有人知道为什么吗?因为当我反汇编 .elf 文件(调用 isr.asm 目标)时,生成的汇编代码似乎是正确的:

isr.elf:     file format elf32-bigarm


Disassembly of section .flash_code_isr_vector:

00000000 <isr_vector>:
   0:   e59ff018    ldr pc, [pc, #24]   ; 20 <isr_vector+0x20>
   4:   e59ff018    ldr pc, [pc, #24]   ; 24 <isr_vector+0x24>
   8:   e59ff018    ldr pc, [pc, #24]   ; 28 <isr_vector+0x28>
   c:   e59ff018    ldr pc, [pc, #24]   ; 2c <isr_vector+0x2c>
  10:   e59ff018    ldr pc, [pc, #24]   ; 30 <isr_vector+0x30>
  14:   e59ff018    ldr pc, [pc, #24]   ; 34 <isr_vector+0x34>
  18:   e59ff018    ldr pc, [pc, #24]   ; 38 <isr_vector+0x38>
  1c:   e59ff018    ldr pc, [pc, #24]   ; 3c <isr_vector+0x3c>
  20:   00000100    andeq   r0, r0, r0, lsl #2
  24:   08000004    stmdaeq r0, {r2}
  28:   08000008    stmdaeq r0, {r3}
  2c:   0800000c    stmdaeq r0, {r2, r3}
  30:   08000010    stmdaeq r0, {r4}
  34:   08000014    stmdaeq r0, {r2, r4}
  38:   08000018    stmdaeq r0, {r3, r4}
  3c:   0800001c    stmdaeq r0, {r2, r3, r4}

Disassembly of section .flash_code_bootloader:

00000100 <bootloader>:
 100:   eafffffe    b   100 <bootloader>

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0:   41000000    mrsmi   r0, (UNDEF: 0)
   4:   1c616561    cfstr64ne   mvdx6, [r1], #-388  ; 0xfffffe7c
   8:   62690001    rsbvs   r0, r9, #1, 0
   c:   00000012    andeq   r0, r0, r2, lsl r0
  10:   05372d52    ldreq   r2, [r7, #-3410]!   ; 0xfffff2ae
  14:   00060a07    andeq   r0, r6, r7, lsl #20
  18:   52080109    andpl   r0, r8, #1073741826 ; 0x40000002
  1c:   Address 0x000000000000001c is out of bounds.

提前致谢。

在您的汇编代码中,您没有将您的部分标记为可分配,因此当您生成二进制文件时它们不会被输出。如果您使用

转储了 header 文件
arm-none-eabi-objdump -x isr.elf

输出看起来类似于:

isr.elf:     file format elf32-bigarm
isr.elf
architecture: arm, flags 0x00000012:
EXEC_P, HAS_SYMS
start address 0x00000000
private flags = 5000200: [Version5 EABI] [soft-float ABI]

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .flash_code_isr_vector 00000040  00000000  00000000  00000034  2**2
                  CONTENTS, READONLY
  1 .flash_code_bootloadery 00000004  00000000  00000000  00000074  2**2
                  CONTENTS, READONLY
  2 .ARM.attributes 0000001d  00000000  00000000  00000078  2**0
                  CONTENTS, READONLY

标志只有CONTENTSREADONLY。它缺少 ALLOC(可分配)标志。由于您的部分似乎也是代码,因此我会考虑通过添加 "ax" 属性来修改 isr.S,例如:

.arm

.global isr_vector
.global bootloader

.section .flash_code_isr_vector,"ax",%progbits
isr_vector:
    LDR     pc, = bootloader /* reset. */
    LDR     pc, = 0x08000004 /* undefined instruction. */
    LDR     pc, = 0x08000008 /* system call. */
    LDR     pc, = 0x0800000C /* prefetch abort. */
    LDR     pc, = 0x08000010 /* data abort. */
    LDR     pc, = 0x08000014 /* reserved. */
    LDR     pc, = 0x08000018 /* IRQ. */
    LDR     pc, = 0x0800001C /* FIQ. */

.section .flash_code_bootloader,"ax",%progbits
bootloader:
    B       .

如果您重建代码,bin 文件应该是 non-zero 并且 ELF headers 现在应该看起来像:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .flash_code_isr_vector 00000040  00000000  00000000  00010000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .flash_code_bootloader 00000004  00000100  00000100  00010100  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .ARM.attributes 0000001d  00000000  00000000  00010104  2**0
                  CONTENTS, READONLY

.section 指令是 documented for ELF 为:

ELF Version

This is one of the ELF section stack manipulation directives. The others are .subsection (see SubSection), .pushsection (see PushSection), .popsection (see PopSection), and .previous (see Previous).

For ELF targets, the .section directive is used like this:

.section name [, "flags"[, @type[,flag_specific_arguments]]]

[snip]

a section is allocatable

d section is a GNU_MBIND section

e section is excluded from executable and shared library.

w section is writable

x section is executable

M section is mergeable

S section contains zero terminated strings

G section is a member of a section group

T section is used for thread-local-storage

? section is a member of the previously-current section’s group, if any

[snip]

The optional type argument may contain one of the following constants:

@progbits section contains data

@nobits section does not contain data (i.e., section only occupies space)

[snip]

Note on targets where the @ character is the start of a comment (eg ARM) then another character is used instead. For example the ARM port uses the % character.