【发布时间】:2022-01-22 03:01:44
【问题描述】:
我正在尝试在汇编中编写裸机代码并使用 GCC 工具链编译 + 链接它。 据我所知,正确的步骤是遵循以下步骤:
- 重启后 - MCU 必须检查向量表并执行重置处理程序,我在其中初始化堆栈指针。
- 执行主代码。 为了完成这个任务,我还需要有相应的链接器脚本。当我尝试执行链接器时,它会引发语法错误。 请指教:
- 链接描述文件中必须更正的内容
- 更正 vtable 和处理程序执行顺序。
代码:
stack_size = 0x400
stack_start = 0x20000000+stack_size
gpiob_base = 0x40010C00
rcc_base = 0x40021000
rcc_apb2enr = rcc_base+0x18
gpio_crl = gpiob_base
gpiob_odr = gpiob_base+0x0C
.syntax unified
.cpu cortex-m3
.thumb
.global main
.global vtable
main:
LDR R0, =rcc_apb2enr
LDR R1, [R0]
LDR R2, =0x8 // Activate 3rd bit in registry
ORR R1, R2
STR R1, [R0]
// Configure GPIO_CRL
LDR R0, =gpio_crl
LDR R1, [R0]
LDR R2, =0xFFFFFF00
AND R1,R1,R2
ORR R1, R1, #0x20
STR R1, [R0] // Reset register
//Configure GPIOB_ODR
LDR R0, =gpiob_odr
LDR R1, [R0]
ORR R1, #0x2
STR R1, [R0]
B .
vtable:
.word stack_start
.word reset_handler
reset_handler:
B main
链接器脚本:
/* - STM32F103C8T6 - Medium Density device
* - RAM: 20K, Flash:64K CPU: 72MHz
*/
ENTRY(reset_handler);
MEMORY {
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
}
SECTIONS
{
/* Section that stores program instructions (code) */
.text : {
. = ALIGN(4);
KEEP(*(.vtable))
*(.text)
*(.text*)
*(.rodata)
*(.rodata*)
. = ALIGN(4);
} > FLASH
_data_flash = .;
// Section that store initialized data - variables
.data : AT(_data_flash){
. = ALIGN(4);
_data_begin = .;
*(.data)
*(.data*)
. = ALIGN(4);
_data_end = .;
} > RAM
/* Section that stores uninitialized data */
.bss :{
_bss_begin = .;
_bss_start_ = _bss_begin;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
_bss_end_ = _bss_end;
} > RAM
/* Here we define stack */
_stack_size = 1024;
_stack_end = ORIGIN(RAM)+LENGTH(RAM);
_stack_begin = _stack_end - _stack_size;
. = _stack_begin;
._stack :{
. = . + _stack_size;
} > RAM
}
._stack :{
. = . + _stack_size;
} > RAM
}
程序反汇编:
pi@mylab:~/assembly $ arm-none-eabi-objdump --disassemble bp.o
bp.o: file format elf32-littlearm
Disassembly of section .text:
00000000 <main>:
0: 480d ldr r0, [pc, #52] ; (38 <reset_handler+0x4>)
2: 6801 ldr r1, [r0, #0]
4: f04f 0208 mov.w r2, #8
8: ea41 0102 orr.w r1, r1, r2
c: 6001 str r1, [r0, #0]
e: 480b ldr r0, [pc, #44] ; (3c <reset_handler+0x8>)
10: 6801 ldr r1, [r0, #0]
12: f06f 02ff mvn.w r2, #255 ; 0xff
16: ea01 0102 and.w r1, r1, r2
1a: f041 0120 orr.w r1, r1, #32
1e: 6001 str r1, [r0, #0]
20: 4807 ldr r0, [pc, #28] ; (40 <reset_handler+0xc>)
22: 6801 ldr r1, [r0, #0]
24: f041 0102 orr.w r1, r1, #2
28: 6001 str r1, [r0, #0]
2a: e7fe b.n 2a <main+0x2a>
0000002c <isr_vector>:
2c: 20000400 .word 0x20000400
30: 00000034 .word 0x00000034
00000034 <reset_handler>:
34: f7ff bffe b.w 0 <main>
38: 40021018 .word 0x40021018
3c: 40010c00 .word 0x40010c00
40: 40010c0c .word 0x40010c0c
【问题讨论】:
-
LDR R0, =stack_start MOV SP, R0不需要,因为它是由硬件在重置时设置的。但是你忘了跳转到main -
还需要将标签声明为拇指函数才能正确生成向量表。你能显示二进制文件开头的反汇编吗?
-
我已将 reset_handler: 子程序指令更改为:B main。因此,一旦调用了 reset_handler,它就会跳转到 main 子例程,并且我添加了 B 。在 main 的 and 处,因此它保持在恒定循环中。当我调用链接器时,它会引发以下错误: arm-none-eabi-ld: warning: cannot find entry symbol handler_reset;默认为 08000000
-
注意你的向量表不是在 0x00000000 或 0x08000000...它不会启动
-
还要注意表中的复位处理程序地址是 0x34 它应该是 0x34|1 = 0x35 芯片才能启动。
标签: assembly gcc stm32 bare-metal