Tal*_*Tal 2 embedded assembly arm
我刚刚开始使用LPC2148 ARM处理器.
我试图了解一些有关创建中断向量的汇编代码.
这是代码:
// Runtime Interrupt Vectors
// -------------------------
Vectors:
b _start // reset - _start
ldr pc,_undf // undefined - _undf
ldr pc,_swi // SWI - _swi
ldr pc,_pabt // program abort - _pabt
ldr pc,_dabt // data abort - _dabt
nop // reserved
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
ldr pc,_fiq // FIQ - _fiq
#if 0
// Use this group for production
_undf: .word _reset // undefined - _reset
_swi: .word _reset // SWI - _reset
_pabt: .word _reset // program abort - _reset
_dabt: .word _reset // data abort - _reset
_irq: .word _reset // IRQ - _reset
_fiq: .word _reset // FIQ - _reset
#else
// Use this group for development
_undf: .word __undf // undefined
_swi: .word __swi // SWI
_pabt: .word __pabt // program abort
_dabt: .word __dabt // data abort
_irq: .word __irq // IRQ
_fiq: .word __fiq // FIQ
__undf: b . // undefined
__swi: b . // SWI
__pabt: b . // program abort
__dabt: b . // data abort
__irq: b . // IRQ
__fiq: b . // FIQ
#endif
.size _boot, . - _boot
.endfunc
Run Code Online (Sandbox Code Playgroud)
我根本不明白这里发生了什么.如果有人能向我解释这个过程,特别是如何在这里使用ldr指令,我将不胜感激.
塔尔
我要删除条件代码,因为它只会使事情变得复杂:
// Runtime Interrupt Vectors
// -------------------------
Vectors:
b _start // reset - _start
ldr pc,_undf // undefined - _undf
ldr pc,_swi // SWI - _swi
ldr pc,_pabt // program abort - _pabt
ldr pc,_dabt // data abort - _dabt
nop // reserved
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
ldr pc,_fiq // FIQ - _fiq
_undf: .word __undf // undefined
_swi: .word __swi // SWI
_pabt: .word __pabt // program abort
_dabt: .word __dabt // data abort
_irq: .word __irq // IRQ
_fiq: .word __fiq // FIQ
__undf: b . // undefined
__swi: b . // SWI
__pabt: b . // program abort
__dabt: b . // data abort
__irq: b . // IRQ
__fiq: b . // FIQ
.size _boot, . - _boot
.endfunc
Run Code Online (Sandbox Code Playgroud)
让我们先看看重置/启动向量:
b _start
Run Code Online (Sandbox Code Playgroud)
该指令是标记为"_start"的代码的无条件分支(跳转),我在您的代码片段中没有看到.基本上它将是初始化堆栈和处理器寄存器的程序集,然后可能某些内存区域可能会跳转到执行大量初始化的C例程.
接下来是执行无效指令时ARM将执行的"未定义"向量(如果我的内存是正确的):
ldr pc, _undf
Run Code Online (Sandbox Code Playgroud)
该指令加载pc寄存器('程序计数器'或指令指针),地址为"_undf"符号.如果我们查看_undf变量,它包含由符号表示的地址__undf.所以ldr pc, _undf指令加载pc了__undf地址 - 跳转到__undf:.
在__undf我们看到:
__undf: b .
Run Code Online (Sandbox Code Playgroud)
这只是同一地址的分支 - 无限循环(.符号表示'此处'或'此位置').
因此,对于大多数这些向量(遵循与未定义向量相同的技术),它们只会跳转到无限循环.您可以使用适合所讨论的向量的代码替换这些标签上的无限循环,尽管许多项目不会,因为这些向量触发将代表某种严重错误.
最后,最有趣的向量槽是IRQ向量:
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
Run Code Online (Sandbox Code Playgroud)
这看起来像是恩智浦设备的处理程序.
它pc使用从相对于pc寄存器的存储器位置读取的值加载寄存器.因为在ARM体系结构上,IRQ向量总是在地址0x00000018(我将忽略可以将向量映射到其他地方的实现或者像使用不同向量模型的Cortex-M3这样的ARM)以及由于指令管道对使用的影响PC用于寻址的寄存器值,该指令将读取的存储器位置,即"向量中断控制器"(VIC)0xFFFFF030中的存储器映射VICVectAddr寄存器的地址:
'apparent' Pipeline offset in effective
PC value effect the opcode address
------------- ------------ ----------- ----------
0x00000018 + 0x00000008 - 0x0000ff0 == 0xfffff030
Run Code Online (Sandbox Code Playgroud)
该器件寄存器将包含刚刚发生的中断的中断处理程序的地址(当然,VIC需要正确初始化,因此它知道该地址).
因此,当ldr pc,[pc,#-0xFF0]指令执行时,它将pc使用适当设备的中断处理程序例程的地址加载寄存器(基本上,跳转到正确的中断处理程序).