如何解决为什么这个函数确实以 1 的偏移量指向自身?
我正在尝试使用 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,asr #26
4: 61656100 cmnvs r5,lsl #2
8: 01006962 tsteq r0,r2,ror #18
c: 00000023 andeq 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,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:
矢量表
向量表包含堆栈的重置值
指针和起始地址,也称为异常向量,用于
所有异常处理程序。第 39 页的图 11 显示了
向量表中的异常向量。最不重要的位
每个向量必须为 1,表示异常处理程序为 Thumb
代码。
因此,LSb = 1 表示该向量指向的指令是 Thumb 指令。 Cortex-M 内核仅支持 Thumb 指令集。编译器知道这一点,并自动使 LSb = 1。如果您以某种方式设法将其设为 0,它将无法工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。