题目是错误的,为什么?????????????????????????????????????????????????
那不一定
这个可以在linker里面设置程序的 entrypoint 为别的函数
windows程序就是 WinMain
dll 就是 dllmain
这个是不一定的哈,我从编译连接的层面说下。
除了我们写的代码逻辑,程序运行还需要一些初始化和程序放回之类的相关程序,他们存放在obj文件里。而我们需要把这些obj和我们自己代码的obj连接在一起,才能生成exe。
由C语言开发系统提供的obj会对main函数进行调用,所以如果我们修改其中的main值,让就会去调用其他函数,也就不用写main了。
也就是说,从main开始,不是C语言本身的语法规则,C需要一个起始点,而C语言的具体实现把这个点命名成了main,如果命名成了其他的名称,起始点就是这个名称代表的函数地址。
对于MCU而言,整个启动过程是从BootRom(芯片厂商提供,一般为startup)开始的,而一般.s文件中mix使用了c语言和汇编语言,如下:
/* Reset Handler */
.thumb_func
.align 2
.globl Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
cpsid i /* Mask interrupts */
/* Init the rest of the registers */
ldr r1,=0
ldr r2,=0
ldr r3,=0
ldr r4,=0
ldr r5,=0
ldr r6,=0
ldr r7,=0
mov r8,r7
mov r9,r7
mov r10,r7
mov r11,r7
mov r12,r7
#ifdef START_FROM_FLASH
/* Init ECC RAM */
ldr r1, =__RAM_START
ldr r2, =__RAM_END
subs r2, r1
subs r2, #1
ble .LC5
movs r0, 0
movs r3, #4
.LC4:
str r0, [r1]
add r1, r1, r3
subs r2, 4
bge .LC4
.LC5:
#endif
/* Initialize the stack pointer */
ldr r0,=__StackTop
mov r13,r0
#ifndef __NO_SYSTEM_INIT
/* Call the system init routine */
ldr r0,=SystemInit
blx r0
#endif
/* Init .data and .bss sections */
ldr r0,=init_data_bss
blx r0
cpsie i /* Unmask interrupts */
bl main
————————————————
原文链接:https://blog.csdn.net/weixin_42814402/article/details/125471634
这个Reset_handler的内容中最后一句很明显的表示了是要跳转到main,这里注释已经写的很清晰了,依次完成了r0到r13的内核系统寄存器初始化,然后是调用了一个叫SystemInit的函数进行系统初始化,最后会跳转到大家再熟悉不过的main函数。也就是说,你可以使他跳转到任意一个函数,并不一定非要从main开始。
上面两位同学说的链接是指编译过程中的link,linker脚本一般会将main函数专门框到一个段内,而这个段一般地址是相对固定的,便于从boot那个hex跳转到当前hex的指定函数,从而完成整个启动过程。和我上面说的“没有boot”直接使用startup跳转本质上是一样的,都是一个跳转,只不过跳转的具体实现方式不同。