分类:
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,这样就可以处理中断服务函数子程序了。
这是我个人的理解,具体是否有错误,请大家指正,欢迎交流!