想象一下,我正在编写一个根本不使用堆栈的汇编语言程序。
为什么Cortex-M要求堆栈指针?即使我不使用它,CPU也会对此堆栈指针执行什么操作(CPU是否需要SP才能运行?我认为SP不是CPU必须运行的。)
我有理由将第一个要执行的指令或程序开始的地址放在第一个地址。
答案 0 :(得分:2)
从技术上讲,CPU不需要运行堆栈指针。但是,它确实需要堆栈指针才能正确地为中断和异常提供服务。它在处理中断之前将某些信息放在堆栈上,以便在中断之后恢复系统状态。理论上,您可以在引导后的第一条指令中遇到异常,因此需要在开始执行之前设置SP。
另外,你熟悉矢量表吗?通常,处理器中的前几个地址无论如何都保留给向量表。向量表包含硬件在处理中断和异常时引用的跳转地址。
答案 1 :(得分:2)
非常欢迎您使用自己的处理器制作自己的芯片,也欢迎您许可ARM产品并修改它们。
皮质m与全尺寸手臂完全有意义。 arm在这个设计中努力使你不必拥有任何汇编语言或者至少没有那么多。引导程序必须做的两件事,以使您从事件处理程序的第一条指令(重置是一个事件)到C函数来处理该事件。一个是堆栈,第二个是保留状态(保存在理想情况下在堆栈上进入下一层功能之前必须保留的寄存器)。他们现在用硬件做这两件事。最初的堆栈指针绝对不是必需的,但是如果你不想在那里放置堆栈地址,那么该地址就无法重新调整用途,但是不管怎么说,无论你放在哪里都会加载到r13中,这就是硬件的工作方式,不要喜欢它找到另一个处理器。第二个不同于全尺寸的臂,矢量现在是矢量而不是指令,因此它们是一个地址,所以你不能把你的指令放在地址0x4。现在,如果你想得到关于这个的肛门,你可以将你的第一条指令放在地址0x000,只要地址0x4的32位值全为零。所以就像一个全尺寸的手臂,在这种情况下,前32位必须是跳跃。
更理智的事情当然是为向量表预留一点空间,也许你的程序集实际上想要服务一些中断(也许你不需要堆栈,因为硬件将使用堆栈写入是否喜欢的指针,如果你不喜欢它,找另一个处理器)。然后在这个保留空间之后放置你的第一个指令组件,机器代码,无论如何,并且像大多数其他处理器系列一样将复位向量指向该地址。大多数都有一个向量表,并不总是在零地址,但在某处,并指向代码所在的其他地方。
您可以在程序前面的8个字节内执行此操作
.cpu cortex-m4
.thumb
.word 0
.word _start
.thumb_func
.globl _start
_start:
/* code starts here*/
或者我愿意打赌这也会有效,只花费4个字节而不是8个。(从技术上讲,它需要4或6个字节或8个,具体取决于你的计算方式。)
.cpu cortex-m4
.thumb
.thumb_func
.globl _start
_start:
b over
.word _start
over:
/* code continues here*/
只要分支肯定会产生两个16位指令。
Disassembly of section .text:
00000000 <_start>:
0: e001 b.n 6 <over>
2: 00000000 andeq r0, r0, r0
00000006 <over>:
6: e7fe b.n 6 <over>
不,没有工作,怎么样
.cpu cortex-m4
.thumb
.thumb_func
.globl _start
_start:
b over
.align
.word _start
over:
/* code continues here*/
b .
啊,好多了。
00000000 <_start>:
0: e002 b.n 8 <over>
2: bf00 nop
4: 00000001 andeq r0, r0, r1
00000008 <over>:
8: e7fe b.n 8 <over>
a: bf00 nop
如果你最终想要做足够的汇编来做一些有用的事情,那么你可能会想要堆栈并且它们只需要在重置时加载堆栈指针就可以节省一些字节数而不必编写代码来执行它在重置处理程序中。
汇编意味着你可以做任何你想做的事情,虽然他们正在迎合群众(C)让他们的生活变得更轻松,一堆,大部分时间你现在可以把直接解决你的C处理函数,bootstrap可以消失。你无法使用全尺寸和先前的手臂解决方案。