我有很多基于拇指和 cortex-m 的示例http://github.com/dwelch67
正如 Joachim 指出的那样,您缺少向量表中的第一个条目,即堆栈指针。cortex-m 没有与 arm 相同的向量表,即使用 arm 指令以 arm 模式启动的向量表。
不过,要完成答案,对于 cortex-m,您可以通过将堆栈指针的起始值放在第一个单词位置来设置堆栈
.cpu cortex-m3
.thumb
.word 0x10008000 /* stack top address */
.word _start /* 1 Reset */
.word hang /* 2 NMI */
.word hang /* 3 HardFault */
.word hang /* 4 MemManage */
您当然可以在运行后手动设置堆栈指针,就像使用 arm 模式或大多数其他处理器一样。
我会让你的代码陷入无限循环,这样,正如所写的那样,你不会陷入未定义的指令等(应该是 0xFFs,在我认为的 cortex-m0 上是未定义的,在 -m3 或 -m4 上armv7 thumb2 支持它可能是一个真正的指令)。
请注意,我没有在矢量上使用 +1。你需要知道你的工具。您需要设置 lsbit 来指示分支上的拇指地址/拇指模式。尽管我从中吸取了教训(必须找到so问题)
Arm/Thumb:在 Thumb 代码中使用 BX,调用 Thumb 函数,或跳转到另一个函数中的 Thumb 指令
使用 gnu 汇编器,如果您将指令 .thumb_func 放在标签之前,则该标签被标记为拇指标签,然后 gnu 工具将使用地址|1。
.thumb_func
.globl _start
_start:
您需要不时地构建和反汇编,以确保您的表正在正确构建并且分支等使用正确的地址。
0: 10008000 andne r8, r0, r0
4: 0000005b andeq r0, r0, fp, asr r0
8: 00000050 andeq r0, r0, r0, asr r0
c: 00000050 andeq r0, r0, r0, asr r0
10: 00000050 andeq r0, r0, r0, asr r0
看,显然我的一个例子中有一个错误......它除了重置之外什么都不做(例子中没有使用中断,所以这就是我不知道的方式)。忘记了 .thumb_func
hang: b .
生产
00000050 <hang>:
50: e7fe b.n 50 <hang>
改成
.thumb_func
hang: b .
向量表转到
00000000 <hang-0x50>:
0: 10008000 andne r8, r0, r0
4: 0000005b andeq r0, r0, fp, asr r0
8: 00000051 andeq r0, r0, r1, asr r0
c: 00000051 andeq r0, r0, r1, asr r0
10: 00000051 andeq r0, r0, r1, asr r0
14: 00000051 andeq r0, r0, r1, asr r0
这很有趣,将代码更改为
.cpu cortex-m3
.thumb
.word 0x10008000 /* stack top address */
.word _start+1 /* 1 Reset */
.word hang+1 /* 2 NMI */
.word hang+1 /* 3 HardFault */
.word hang /* 4 MemManage */
.word hang /* 5 BusFault */
它并没有真正做一个加一,而是一个或一。
00000000 <hang-0x50>:
0: 10008000 andne r8, r0, r0
4: 0000005b andeq r0, r0, fp, asr r0
8: 00000051 andeq r0, r0, r1, asr r0
c: 00000051 andeq r0, r0, r1, asr r0
10: 00000051 andeq r0, r0, r1, asr r0
这有点令人不安。最重要的是,有两件事,使用 cortex-m 您可以在向量表中设置堆栈指针,第二,在开始新项目时反汇编并检查向量表以确保它是您所期望的。特别是如果它没有做你认为它应该做的事情。