Chinaunix首页 | 论坛 | 博客
  • 博客访问: 394213
  • 博文数量: 105
  • 博客积分: 4100
  • 博客等级: 上校
  • 技术积分: 1040
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-27 19:57
文章存档

2012年(1)

2011年(9)

2010年(4)

2009年(25)

2008年(66)

我的朋友

分类:

2008-07-28 09:33:52

 

关于arm中断地址解析函数的一段代码完全解析

先把指令给出,下面是三星公司附带的init.s程序中的一个宏定义,用于中断地址解析

MACRO

$HandlerLabel HANDLER $HandleLabe;这是带了两个参数的宏定义,具体语法不明白可参看相关的ARM指令的汇编手册

$HandlerLabel

Sub    sp,sp ,#4;

stmfd sp!,{r0};

ldr   r0,=$HandleLabel

ldr   r0,[r0];

str  r0 {sp #4};

ldmfd   sp!,{r0,pc}

首先第一条指令,sub sp,sp,#4,费减了我大半天时间,为什么压栈前非得减4,弄了好长时间才把整段代码看明白,人比较笨,没办法,只得一步一步爬着走。

先解释第一条,将堆栈指针的内容减去4是有原因的,是为了给PC留4个字节,

stmfd sp!,{r0};这条指令是一条压栈操作,执行它后sp的指向的地址将会自动加或者减,具体加还是减得取决于你所定义的堆栈操作方式。我在前边用的是满递减方式,故在此执行这条指令将会导致SP的值自动减

ldr   r0,=$HandleLabel

ldr   r0,[r0];

这两条批令不解释,很简单,是将中断服务函数的地址装入了r0

str  r0 {sp ,#4};这条指令,首先明白它并不是一条压栈的指令,却做到了压栈的作用,他将r0中的内容保存到sp+4指向的堆栈空间。

ldmfd   sp!,{r0,pc}这条指令也让我想了很长时间,后来想想自己太笨了,这是一条出栈指令,同时也会使堆栈指针自动更新,便是使用得注意顺序,得按后进先出原则的堆栈操作规则来,在此虽然此指令ldr   r0,[r0](存入的是ISR地址)后存入进去,但是它的地址却比先存入进去的原寄存器r0的地址高,(stmfd sp!,{r0};),也就是说当前SP是指向stmfd sp!,{r0}这条令压入栈后的地址,所以出栈时先出来的是这条指令压入的内容,后一个是ISR的地址,将其出栈后给予PC,这样就可以处理中断服务函数子程序了。

这是我个人的理解,具体是否有错误,请大家指正,欢迎交流!

阅读(555) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~