金牌会员
 
- 积分
- 1046
- 金钱
- 1046
- 注册时间
- 2017-5-19
- 在线时间
- 335 小时
|
发表于 2017-12-19 14:03:50
|
显示全部楼层
Cortex M3 权威指南(中文).PDF 169页 可能有你需要的
[mw_shl_code=c,true]// 使用C写成的SVC服务例程,接受一个指针参数( pwdSF):堆栈栈的起始地址。
// pwdSF[0] = R0 , pwdSF[1] = R1
// pwdSF[2] = R2 , pwdSF[3] = R3
// pwdSF[4] = R12, pwdSF[5] = LR
// pwdSF[6] = 返回地址(入栈的PC)
// pwdSF[7] = xPSR
unsigned long svc_handler(unsigned int* pwdSF)
{
unsigned int svc_number;
unsigned int svc_r0;
unsigned int svc_r1;
unsigned int svc_r2;
unsigned int svc_r3;
int retVal; //用于存储返回值
svc_number = ((char *) pwdSF[6])[-2]; // 没想到吧, C的数组能用得这么绝!
svc_r0 = ((unsigned long) pwdSF[0]);
svc_r1 = ((unsigned long) pwdSF[1]);
svc_r2 = ((unsigned long) pwdSF[2]);
svc_r3 = ((unsigned long) pwdSF[3]);
printf (“SVC number = %xn”, svc_number);
printf (“SVC parameter 0 = %x\n”, svc_r0);
printf (“SVC parameter 1 = %x\n”, svc_r1);
printf (“SVC parameter 2 = %x\n”, svc_r2);
printf (“SVC parameter 3 = %x\n”, svc_r3);
//做一些工作,并且把返回值存储到retVal中
pwdSF[0]=retVal;
return 0;
}
注意,这个函数返回的其实不是0!进一步地,灰色的文字只是用于哄编译器开心的—
—让它认为这个函数是个有返回值的函数,而且确实返回一个数值了,于是不再吵闹着说有
错或警告什么的。那返回的是啥?当然是retVal啦!有点迷糊么?往下看就知道了。
原来, SVC服务例程不能像普通的C函数那样——通过把原型声明为”unsigned int func()”,
再在末尾来一句”return xx;”来返回。因为这种常规的作法在所有的ARM中其实是把返回值
放到R0里。但是别忘了,这个函数可是异常服务例程,它的返回可是享受“异常返回”的待
遇的——伴随着一个硬件控制的自动出栈行为,这会从堆栈中重建R0的值,从而覆盖“ return”
指定的值。因此,它必须把返回值写到堆栈中R0的位置,才能借自动出栈之机返回自己的值
( pwdSF[0]=retVal)。
这下可真相大白了!虽然内部暗流汹涌,但是从应用程序的表面上看还是风平浪静——
对于系统服务函数来说,这种独特的返回方式与普通的return xx效果是相同的,依然可以用
普通的形式接收返回值。怎么样,这招够狠吧!其实,在写系统软件时,这根本算不上耍狠,
只不过是寻常的基本功罢了,要不然怎么说C是“低级高级语言”呢。而病毒/木马所采用的
“堆栈/缓冲区溢出攻击”,那才算真正的狠招呢,但是它们原理是同根的。可见,对底层
理解得深刻,能让我们写出更好,更强大的程序来。[/mw_shl_code] |
|