登录注册
论坛
裸片初长成(初级)
4997
19
为了代码的精简有时候不得不用到寄存器地方直接访问的方法,下面有两种表达方式,但结果却完全不同,谁能说说原因?
1.
u32 addr;
#define ADC_REG(addr) (*((volatile u32*)addr))
addr = (u32)(&LPC_ADC->ADDR0) + chNum*ADC_OFFSET; while ((ADC_REG(addr) & ADC_DONE) == 0) { ; // 第一次转换结果丢弃 }
2.
while ((ADC_REG((u32)(&LPC_ADC->ADDR0) + chNum*ADC_OFFSET) & ADC_DONE) == 0) { ; // 第一次转换结果丢弃 }
唯一的区别就是:1中把计算出来的地方放入一个变量中,而2却是直接参与运算,你猜猜那种才能得到正确的结果,为什么???????
扫一扫,分享给好友
两种方式的反汇编
1.bmp (369.07 KB, 下载次数: 0) 下载附件 保存到相册 2012-7-8 21:09 上传
1.bmp (369.07 KB, 下载次数: 0)
下载附件 保存到相册
2012-7-8 21:09 上传
2.bmp (487.55 KB, 下载次数: 0) 下载附件 保存到相册 2012-7-8 21:09 上传
2.bmp (487.55 KB, 下载次数: 0)
通过分析仿真以上两个汇编代码我们可以发现:
1. 方法1中首先是把寄存器地址计算出来放入R2中的,我们每次读取寄存器的值,只要通过读取R2即可;但是,方法2并没有把寄存器地址放入一个固定的寄存器,而是通过与R0的计算进行,并且篡改了寄存器R0的值,导致我们要第二次读取时,需要重新计算地址。
2. 方法2中多了一种R6,LSL #2的运算,导致计算的寄存器地址并不正确,所以无法获取正确的值。
总结:
很多时候,我们为了代码精简,把一大串运算放入一个表达式中,总是得不都正确的结果,而观看C代码也发现不了任何问题,在这种情况下我们尽量把表达式拆分,即可观看每一步的结果,也减少了出错的机会;当然我们也可以观看反汇编代码,来寻找问题。
特别是在读取ARM内部寄存器时,我们为了省事,总是直接利用寄存器值,往往也会导致同样的问题发生,在这种情况下,我们尽量还是要先把寄存器的值放入一个变量在加以运用。
一粒金砂(初级)
25
0
发表回复 回帖后跳转到最后一页
曾经的版主且威望大于2000,或对EEWORLD论坛有突出贡献的坛友
EEWorld Datasheet 技术支持
查看 »