【发布时间】:2013-04-22 20:47:02
【问题描述】:
我想知道在基于 ARM 的微控制器上编写 SVC 调用的正确方法。
到目前为止,我的理解是 ARM 有一个异常向量表,这意味着任何程序中的第一条指令都必须分支到适当的处理程序:
RESET ;Handles reset
UNDEFINED ;Undefined instructions
SVC BL SVC_Entry
PRE_ABORT ;Prefetch abort
DAT_ABORT ;Data abort
然后,每次运行 SVC 指令时,模式切换到监督模式,SVC 提供的编号存储在 R0 中,程序将跳转到适当的处理程序:
;== Handling SVC calls ========================================================
Max_SVC EQU 1
SVC_Entry CMP R0, #Max_SVC ;Check upper limit
BHI SVC_end ;Does nothing if unknown
ADD R0, PC, R0, LSL #2 ;Calculate table address
LDR PC, [R0, #0]
Jump_table DEFW SVC_0 ;Halt
DEFW SVC_1 ;Print string
;== SVC calls ================================================================
SVC_1 B SVC_end
SVC_end MOVS PC, LR ;Exiting
所以,如果我们有这些说明:
ADR R1, string ;R1 points to the string
SVC 1 ;SVC_1 handles the printing
程序必须切换到主管模式,将数字“1”存储在 R0 中,然后按照跳转表分支到 SVC_1,运行代码并切换回用户模式。
这是正确的吗?我做得对吗?
到目前为止我遇到的问题是我的编译器对这一行说“操作员预期”:
SVC BL SVC_Entry
在互联网上很难找到有关此主题的信息,我只想知道如何在 ARM 微控制器上正确使用 SVC 调用。
非常感谢。
编辑: 底层处理器是时钟频率约为 240 MHz 的 ARM9。这住在 一个 AT91 微控制器。它所在的实验室板已经过修改,以满足我大学的需要。
代码通过串行端口使用定制程序加载到板上。该程序还允许调试。
【问题讨论】:
-
您的目标是什么微控制器或系列? arm7tdmi?皮质-m?
-
你需要这样的东西,
SVC: B SVC_Entry。请注意,:冒号使其成为标签。将其命名为 svc_vec 可能更好,所以是svc_vec: b SVC_Entry。另一个问题,如果你使用BL,你会杀死user返回地址。您可以使用R0或您希望建立的任何约定;检查指令通常很慢。不要忘记设置 supervisor 堆栈和模式。您可能希望在更改之前保存一些 user 寄存器;除非你在调用约定中定义。 -
@dwelch 传统上,SVC 索书号被编码在操作码中(这就是 Acorn 在 RISCOS 中的做法)。但是,ARM Linux 和 iOS 都将它传递到一个寄存器中——从性能角度来看,这在所有具有哈佛架构的 ARM 设备上可能是有意义的,因为它避免了一条只有 4 个字节可能被读取的行污染 D-Cache ,以及相应的缓存行填充。
-
@artlessnoise,我已经尝试按照你的建议命名它,编译器说:找不到助记符。
-
'Mnemonic not found' 意味着汇编器仍然认为你的标签是一条指令。您应该使用您现在拥有的确切代码更新您的问题。 大部分你勾勒出来的似乎是正确的。您实际上不需要向量表中的标签,因为 dwelch 显示 cortex-m 上的 Thumb。 真实代码越多越好。
标签: assembly arm hardware microcontroller