gpt4 book ai didi

c - 为什么这个函数确实以偏移量 1 指向它自己?

转载 作者:行者123 更新时间:2023-12-04 00:51:40 26 4
gpt4 key购买 nike

我正在尝试使用 C 为 Nucleo-64 Stm32F401re 板编写裸机闪烁程序。然而,在开始调试错误时(它还没有闪烁)我发现了一个奇怪的地址,我找不到任何解释。这是反汇编相关部分的输出:

    blink.elf:     file format elf32-littlearm


Disassembly of section .text:

08000000 <isr_vector_table>:
8000000: 20018000 andcs r8, r1, r0
8000004: 08000009 stmdaeq r0, {r0, r3}

08000008 <Reset_Handler>:
8000008: b480 push {r7}
800000a: af00 add r7, sp, #0
800000c: bf00 nop
800000e: 46bd mov sp, r7
8000010: bc80 pop {r7}
8000012: 4770 bx lr

Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
0: 00002d41 andeq r2, r0, r1, asr #26
4: 61656100 cmnvs r5, r0, lsl #2
8: 01006962 tsteq r0, r2, ror #18
c: 00000023 andeq r0, r0, r3, lsr #32
10: 2d453705 stclcs 7, cr3, [r5, #-20] ; 0xffffffec
14: 0d06004d stceq 0, cr0, [r6, #-308] ; 0xfffffecc
18: 02094d07 andeq r4, r9, #448 ; 0x1c0
1c: 01140412 tsteq r4, r2, lsl r4
20: 03170115 tsteq r7, #1073741829 ; 0x40000005
24: 01190118 tsteq r9, r8, lsl r1
28: 061e011a ; <UNDEFINED> instruction: 0x061e011a
2c: Address 0x0000002c is out of bounds.

Reset_Handler 函数本身在正确的地址上,但通过在代码中使用它的名称作为指针,它进一步指向了一个地址!下面是相应的代码:

extern int _stack_top; // bigger Memory Adress

void Reset_Handler (void);

__attribute__((section(".isr_vector"))) int* isr_vector_table[] = {

(int*)&_stack_top,
(int*)Reset_Handler
};

void Reset_Handler (void) {

}

我使用的链接器脚本与大多数教程中使用的基本相同。

OUTPUT_ARCH(arm)
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
ENTRY(Reset_Handler)

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
}

_stack_top = ORIGIN(SRAM)+LENGTH(SRAM);

SECTIONS
{







.text :
{
. = ALIGN(4);
*(.isr_vector)
*(.text*)
*(.glue_7)
*(.glue_7t)
*(.eh_frame)
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .;
} > FLASH

.rodata :
{
. = ALIGN(4);
*(.rodata*)
. = ALIGN(4);
} > FLASH

.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH

.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH



.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH

.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH

.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH



. = ALIGN(4);
_sidata = LOADADDR(.data);

.data :
{
. = ALIGN(4);
_sdata = .;
*(.data*)
. = ALIGN(4);
_edata = .;
} > SRAM AT > FLASH

.bss :
{
. = ALIGN(4);
_sbss = .;
__bss_start__ = _sbss;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
} > SRAM

/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}

.ARM.attributes 0 : { *(.ARM.attributes) }



}

那么为什么存储在 isr_vector_table 中的地址是 08000009 而不是 08000008?到目前为止,我可以将其更改为正确值的唯一方法是通过对该值进行硬编码或为 Reset_Handler 定义一个额外的部分,这样我就可以将该地址用作另一个外部值,如 _stack_top。

以下是我用于编译的命令,因为我不知道是否需要它们来找到答案:

cd C:/bare_metal
arm-none-eabi-gcc.exe -g main.c -o blink.elf -Wall -T STM32F4.ld -mcpu=cortex-m4 -mthumb --specs=nosys.specs -nostdlib -O0
arm-none-eabi-objdump.exe -D blink.elf

最佳答案

摘自STM32F4的编程手册PM0214:

Vector table
The vector table contains the reset value of the stackpointer, and the start addresses, also called exception vectors, forall exception handlers. Figure 11 on page 39 shows the order of theexception vectors in the vector table. The least-significant bit ofeach vector must be 1, indicating that the exception handler is Thumbcode.

因此,LSb = 1 表示该 vector 指向的指令是 Thumb 指令。 Cortex-M 内核仅支持 Thumb 指令集。编译器知道这一点,并自动使 LSb = 1。如果您以某种方式设法使它成为 0,它将无法工作。

关于c - 为什么这个函数确实以偏移量 1 指向它自己?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65884094/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com